Ticket #98: ListUI_And_Sorting.diff
File ListUI_And_Sorting.diff, 40.6 KB (added by , 20 years ago) |
---|
-
mythcontrols/mythcontrols/mythcontrols.cpp
36 36 37 37 /* MythTV includes */ 38 38 #include <mythtv/mythcontext.h> 39 #include <mythtv/uitypes.h>40 39 #include <mythtv/mythdialogs.h> 41 #include <mythtv/dialogbox.h>42 #include <mythtv/xmlparse.h>43 40 #include <mythtv/themedmenu.h> 44 #include <mythtv/mythdbcon.h>45 41 46 42 using namespace std; 47 43 48 44 #include "mythcontrols.h" 49 45 #include "keygrabber.h" 50 46 51 /**52 * @class ConflictResolver53 * @brief A MythDialog that notifies the user of conflicts.54 */55 class ConflictResolver : public MythPopupBox56 {57 47 58 public:59 ConflictResolver(MythMainWindow *window, ActionID *conflict)60 : MythPopupBox(window, "conflictresolver")61 {62 QString warning = "The key you have chosen is already bound to "63 + conflict->action() + " in the " + conflict->context()64 + " context; please rebind it before binding this key.";65 66 addLabel("Action Conflict", Large, false);67 addLabel(warning, Small, true);68 }69 48 70 71 ConflictResolver(MythMainWindow *window)72 : MythPopupBox(window,"conflictresolver")73 {74 75 QString warning;76 warning = "This action is manditory and needs at least one key bound ";77 warning += "to it. Instead, try rebinding with another key.";78 79 addLabel("Manditory Action", Large, false);80 addLabel(warning, Small, true);81 }82 };83 84 85 49 /* comments in header */ 86 MythControls::MythControls (MythMainWindow *parent, const char *name) 50 MythControls::MythControls (MythMainWindow *parent, const char *name, 51 bool & ui_ok) 87 52 :MythThemedDialog(parent, "controls", "controls-", name) 88 53 { 54 /* Nullify keybindings so the deconstructor knows not to delete it */ 55 this->key_bindings = NULL; 56 89 57 /* load up the ui components */ 90 loadUI(); 58 if ((ui_ok = loadUI())) 59 { 60 /* for starters, load this host */ 61 loadHost(gContext->GetHostName()); 91 62 92 /* for starters, load this host */ 93 loadHost(gContext->GetHostName()); 94 95 /* update the information */ 96 refreshKeyInformation(); 63 /* update the information */ 64 refreshKeyInformation(); 65 } 97 66 } 98 67 99 68 100 69 101 70 /* comments in header */ 102 MythControls::~MythControls() { delete (this->key_bindings); }71 MythControls::~MythControls() { delete this->key_bindings; } 103 72 104 73 105 74 … … 109 78 /* the return value of the method */ 110 79 bool retval = true; 111 80 112 /* by default, there is no popup */113 popup = NULL;114 115 81 /* Get the UI widgets that we need to work with */ 116 description = getUITextType("description");117 if (!description){118 VERBOSE(VB_ALL, " Unable to load action_description");82 if ((description = getUITextType("description")) == NULL) 83 { 84 VERBOSE(VB_ALL, "MythControls: Unable to load action_description"); 119 85 retval = false; 120 86 } 121 87 122 control_tree_list=getUIManagedTreeListType("controltree"); 123 if (!control_tree_list) 88 if ((control_list=getUIListTreeType("controltree")) == NULL) 124 89 { 125 VERBOSE(VB_ALL, " Unable to load controltree");90 VERBOSE(VB_ALL, "MythControls: Unable to load controltree"); 126 91 retval = false; 127 92 } 128 93 else { 129 94 130 95 /* set some parameters for the tree */ 131 control_tree_list->showWholeTree(true); 132 control_tree_list->colorSelectables(true); 133 focused=control_tree_list; 96 focused=control_list; 97 control_list->setActive(true); 134 98 } 135 99 136 100 /* Check that all the buttons are there */ 137 101 if ((action_buttons[0] = getUITextButtonType("action_one")) == NULL) 138 102 { 139 VERBOSE(VB_ALL, " Unable to load first action button");103 VERBOSE(VB_ALL, "MythControls: Unable to load first action button"); 140 104 retval = false; 141 105 } 142 106 else if ((action_buttons[1] = getUITextButtonType("action_two")) == NULL) 143 107 { 144 VERBOSE(VB_ALL, " Unable to load second action button");108 VERBOSE(VB_ALL, "MythControls: Unable to load second action button"); 145 109 retval = false; 146 110 } 147 111 else if ((action_buttons[2] = getUITextButtonType("action_three")) == NULL) 148 112 { 149 VERBOSE(VB_ALL, " Unable to load thrid action button");113 VERBOSE(VB_ALL, "MythControls: Unable to load thrid action button"); 150 114 retval = false; 151 115 } 152 116 else if ((action_buttons[3] = getUITextButtonType("action_four")) == NULL) 153 117 { 154 VERBOSE(VB_ALL, " Unable to load fourth action button");118 VERBOSE(VB_ALL, "MythControls: Unable to load fourth action button"); 155 119 retval = false; 156 120 } 157 121 … … 177 141 { 178 142 focused = action_buttons[0]; 179 143 action_buttons[0]->takeFocus(); 180 control_tree_list->looseFocus(); 144 control_list->looseFocus(); 145 control_list->setActive(false); 181 146 } 182 147 else 183 148 { … … 220 185 221 186 if (action == "MENU" || action == "INFO") 222 187 { 223 /* bring up the menu */224 this->actionMenu();188 OptionsMenu popup(gContext->GetMainWindow()); 189 if (popup.getOption() == OptionsMenu::SAVE) save(); 225 190 } 226 191 else if (action == "SELECT") 227 192 { 228 if (focused == control_ tree_list)193 if (focused == control_list) 229 194 { 230 if (control_tree_list->getActiveBin() == 1) 231 control_tree_list->pushDown(); 232 else 233 focusButton(0); 195 if (control_list->getDepth() == 0) control_list->MoveRight(); 196 else focusButton(0); 234 197 } 235 198 else { 236 popup = new MythPopupBox(gContext->GetMainWindow(),"decision"); 237 popup->addLabel(tr("Modify Action"),MythPopupBox::Large,false); 238 popup->addButton(tr("Set Binding"),this, SLOT(captureKey())); 239 popup->addButton(tr("Remove Binding"),this, SLOT(deleteKey())); 240 popup->addButton(tr("Cancel"), this, 241 SLOT(killPopup()))->setFocus(); 242 popup->ShowPopup(); 199 ActionMenu popup(gContext->GetMainWindow()); 200 int result = popup.getOption(); 201 if (result == ActionMenu::SET) addKeyToAction(); 202 else if (result == ActionMenu::REMOVE) deleteKey(); 243 203 } 244 204 } 245 205 else if (action == "ESCAPE") 246 206 { 247 if (focused == control_ tree_list)207 if (focused == control_list) 248 208 { 249 209 /* ask the user to save if there are unsaved changes*/ 250 210 if (key_bindings->hasChanges()) 251 211 { 252 popup = new MythPopupBox(gContext->GetMainWindow(), 253 "unsaged"); 254 popup->addLabel(tr("Unsaged Changes"), 255 MythPopupBox::Large, 256 false); 257 258 popup->addLabel(tr("Would you like to save now?")); 259 popup->addButton(tr("Save"), this, 260 SLOT(save()))->setFocus(); 261 popup->addButton(tr("Exit"), this, SLOT(killPopup())); 262 popup->ExecPopup(this, SLOT(killPopup())); 212 UnsavedMenu popup(gContext->GetMainWindow()); 213 if (popup.getOption() == UnsavedMenu::SAVE) save(); 263 214 } 264 215 265 216 /* let the user exit */ … … 269 220 { 270 221 /* take focus away from the button */ 271 222 focused->looseFocus(); 272 control_tree_list->takeFocus(); 273 focused = control_tree_list; 223 focused = control_list; 224 control_list->takeFocus(); 225 control_list->setActive(true); 274 226 } 275 227 } 276 else if ( action == "UP")228 else if ((action == "UP") && (focused == control_list)) 277 229 { 278 if (focused == control_tree_list) 279 { 280 control_tree_list->moveUp(); 281 refreshKeyInformation(); 282 } 283 else focusButton(-1); 230 control_list->MoveUp(); 231 refreshKeyInformation(); 284 232 } 285 else if ( action == "DOWN")233 else if ((action == "DOWN") && (focused == control_list)) 286 234 { 287 if (focused == control_tree_list) 288 { 289 control_tree_list->moveDown(); 290 refreshKeyInformation(); 291 } 292 else focusButton(1); 235 control_list->MoveDown(); 236 refreshKeyInformation(); 293 237 } 294 238 else if (action == "LEFT") 295 239 { 296 if (focused == control_tree_list)240 if (focused==control_list) 297 241 { 298 control_ tree_list->popUp();242 control_list->MoveLeft(); 299 243 refreshKeyInformation(); 300 244 } 301 245 else focusButton(-1); 302 246 } 303 247 else if (action == "RIGHT") 304 248 { 305 if (focused == control_ tree_list)249 if (focused == control_list) 306 250 { 307 control_tree_list->pushDown(); 308 refreshKeyInformation(); 251 if (control_list->getDepth() == 0) 252 { 253 control_list->MoveRight(); 254 refreshKeyInformation(); 255 } 309 256 } 310 257 else focusButton(1); 311 258 } 312 else if ( action == "PAGEUP")259 else if ((action == "PAGEUP") && (focused == control_list)) 313 260 { 314 if (focused == control_tree_list) 315 { 316 control_tree_list->pageUp(); 317 refreshKeyInformation(); 318 } 261 control_list->MoveUp(UIListTreeType::MovePage); 262 refreshKeyInformation(); 319 263 } 320 else if ( action == "PAGEDOWN")264 else if ((action == "PAGEDOWN") && (focused == control_list)) 321 265 { 322 if (focused == control_tree_list) 323 { 324 control_tree_list->pageDown(); 325 refreshKeyInformation(); 326 } 266 control_list->MoveDown(UIListTreeType::MovePage); 267 refreshKeyInformation(); 327 268 } 328 269 else handled = false; 329 270 } … … 363 304 /* comments in header */ 364 305 QString MythControls::getCurrentContext(void) const 365 306 { 366 if (control_tree_list->getActiveBin() == 2) 367 return control_tree_list->getCurrentNode()->getParent()->getString(); 368 else if (control_tree_list->getActiveBin() == 1) 369 return control_tree_list->getCurrentNode()->getString(); 307 UIListGenericTree *current = control_list->GetCurrentPosition(); 308 if (control_list->getDepth() == 1 ) 309 return current->getParent()->getString(); 310 else if (control_list->getDepth() == 0) 311 return current->getString(); 370 312 else 371 313 return ""; 372 314 } … … 376 318 /* comments in header */ 377 319 QString MythControls::getCurrentAction(void) const 378 320 { 379 if (control_ tree_list->getActiveBin() == 2)380 return control_ tree_list->getCurrentNode()->getString();321 if (control_list->getDepth() == 1) 322 return control_list->GetCurrentPosition()->getString(); 381 323 else 382 324 return ""; 383 325 } … … 389 331 390 332 /* create the key bindings and the tree */ 391 333 key_bindings = new KeyBindings(hostname); 392 context_tree = new GenericTree(hostname, 0, false);393 334 QStringList context_names = key_bindings->getContexts(); 394 335 395 for (size_t i = 0; i < context_names.size(); i++) { 336 /* Alphabetic order, but jump and global at the top */ 337 context_names.sort(); 338 context_names.remove(JUMP_CONTEXT); 339 context_names.remove(GLOBAL_CONTEXT); 340 context_names.insert(context_names.begin(), 1, GLOBAL_CONTEXT); 341 context_names.insert(context_names.begin(), 1, JUMP_CONTEXT); 396 342 397 GenericTree *context_node = new GenericTree(context_names[i], i, true);343 UIListGenericTree *root = new UIListGenericTree(NULL, "ROOT"); 398 344 399 /* add the context to the tree of contexts */ 400 context_tree->addNode(context_node); 345 for (size_t i = 0; i < context_names.size(); i++) 346 { 347 UIListGenericTree *context_node; 348 context_node = new UIListGenericTree(root, context_names[i], 349 context_names[i]); 401 350 402 351 QStringList action_names = key_bindings->getActions(context_names[i]); 352 action_names.sort(); 403 353 404 354 /* add all actions to the context */ 405 355 for (size_t j = 0; j < action_names.size(); j++) 406 context_node->addNode(action_names[j], j, true);407 408 /* put the data in the tree */409 control_tree_list->assignTreeData(context_node);356 { 357 new UIListGenericTree(context_node, action_names[j], 358 action_names[j]); 359 } 410 360 } 411 }412 361 413 414 415 void MythControls::killPopup() 416 { 417 if (this->popup == NULL) return; 418 419 this->popup->hide(); 420 delete this->popup; 421 this->popup = NULL; 422 setActiveWindow(); 362 control_list->SetTree(root); 363 control_list->setActive(true); 423 364 } 424 365 425 366 426 367 427 368 /* comments in header */ 428 void MythControls::actionMenu()429 {430 if (popup != NULL) return;431 432 popup = new MythPopupBox(gContext->GetMainWindow(), "editaction");433 popup->addButton(tr("Save Changes"), this, SLOT(save()));434 popup->addButton(tr("Cancel"),this, SLOT(killPopup()))->setFocus();435 popup->ShowPopup(this, SLOT(killPopup()));436 }437 438 439 440 void MythControls::captureKey()441 {442 killPopup();443 444 KeyGrabPopupBox * kg = new KeyGrabPopupBox(gContext->GetMainWindow());445 446 kg->addOKButton(kg->addButton(tr("OK"), this, SLOT(addKeyToAction())));447 kg->addButton(tr("Cancel"), this, SLOT(killPopup()));448 this->popup = (MythPopupBox*)kg;449 this->popup->ShowPopup(this,SLOT(killPopup()));450 }451 452 453 454 369 void MythControls::deleteKey() 455 370 { 456 457 killPopup();458 459 371 size_t b = focusedButton(); 460 372 QString action = getCurrentAction(), context = getCurrentContext(); 461 373 QStringList keys = key_bindings->getActionKeys(context, action); … … 463 375 { 464 376 if (!key_bindings->removeActionKey(context, action, keys[b])) 465 377 { 466 this->popup = new ConflictResolver(gContext->GetMainWindow());467 this->popup->ExecPopup(this, SLOT(killPopup()));378 InvalidBindingPopup popup(gContext->GetMainWindow()); 379 popup.getOption(); 468 380 } 469 381 else refreshKeyInformation(); 470 382 } … … 472 384 473 385 474 386 387 /* method description in header */ 388 bool MythControls::resolveConflict(ActionID *conflict, int level) 389 { 390 MythMainWindow *window = gContext->GetMainWindow(); 391 392 /* prevent a fatal binding */ 393 if (level == KeyBindings::Error) 394 { 395 InvalidBindingPopup popup(gContext->GetMainWindow(), 396 conflict->action(), 397 conflict->context()); 398 popup.getOption(); 399 return false; 400 } 401 else 402 { 403 /* warn the user that this could conflict */ 404 QString message = "This kebinding may conflict with "; 405 message += conflict->action() + " in the " + conflict->context(); 406 message += " context. Do you want to bind it anyways?"; 407 408 if (MythPopupBox::show2ButtonPopup(window, "Conflict Warning", 409 message,"Bind Key","Cancel",0)) 410 return false; 411 } 412 413 return true; 414 } 415 416 417 418 /* method description in header */ 475 419 void MythControls::addKeyToAction(void) 476 420 { 421 /* grab a key from the user */ 422 KeyGrabPopupBox *kg = new KeyGrabPopupBox(gContext->GetMainWindow()); 423 int result = kg->ExecPopup(kg,SLOT(cancel())); 424 QString key = kg->getCapturedKey(); 425 delete kg; 426 427 /* go no further if canceled */ 428 if (result == 0) return; 429 430 /* get the keys for the selected action */ 477 431 size_t b = focusedButton(); 478 QString newkey = ((KeyGrabPopupBox*)popup)->getCapturedKeyEvent();479 432 QString action = getCurrentAction(), context = getCurrentContext(); 480 433 QStringList keys = key_bindings->getActionKeys(context, action); 434 435 /* dont bother rebinding the same key */ 436 if (keys[b] == key) return; 437 438 bool bind = false; 439 int level; 440 441 /* get the potential conflict */ 481 442 ActionID *conflict = NULL; 443 if ((conflict = key_bindings->conflicts(context, key, level))) 444 bind = resolveConflict(conflict, level); 482 445 483 /* having got the key, kill the key grabber */ 484 killPopup(); 446 delete conflict; 485 447 448 /* dont bind if we shouldn't bind */ 449 if (!bind) return; 450 451 /* finally bind or rebind a key to the action */ 486 452 if (b < keys.count()) 487 { 488 /* dont replace with the same key */ 489 if (keys[b] != newkey) { 490 if ((conflict = key_bindings->conflicts(context, newkey))) 491 { 492 this->popup = new ConflictResolver(gContext->GetMainWindow(), 493 conflict); 494 this->popup->ExecPopup(this, SLOT(killPopup())); 495 } 496 else key_bindings->replaceActionKey(context,action,newkey,keys[b]); 497 } 498 } 499 else { 500 if ((conflict = key_bindings->conflicts(context, newkey))) 501 { 502 this->popup = new ConflictResolver(gContext->GetMainWindow(), 503 conflict); 504 this->popup->ExecPopup(this, SLOT(killPopup())); 505 } 506 else key_bindings->addActionKey(context, action, newkey); 507 } 453 key_bindings->replaceActionKey(context,action, key, keys[b]); 454 else 455 key_bindings->addActionKey(context, action, key); 508 456 509 /* delete the conflict and hide the popup*/510 if (conflict) {511 delete conflict;512 killPopup();513 }514 515 457 refreshKeyInformation(); 516 458 } 517 459 518 void MythControls::save(void) {519 key_bindings->commitChanges();520 killPopup();521 }522 523 460 #endif /* MYTHCONTROLS_CPP */ -
mythcontrols/mythcontrols/keybindings.cpp
49 49 50 50 51 51 ActionID * KeyBindings::conflicts(const QString & context_name, 52 const QString & key ) const52 const QString & key, int &level) const 53 53 { 54 54 const ActionList &ids = actionset.getActions(key); 55 55 … … 60 60 /* check the contexts of the other bindings */ 61 61 for (size_t i = 0; i < ids.count(); i++) 62 62 { 63 if (ids[i].context() == JUMP_CONTEXT) return new ActionID(ids[i]); 64 else if (ids[i].context() == context_name) return new ActionID(ids[i]); 63 /* jump points, then global, then the same context */ 64 if (ids[i].context() == JUMP_CONTEXT) { 65 level = KeyBindings::Error; 66 return new ActionID(ids[i]); 67 } 68 else if (ids[i].context() == context_name) { 69 level = KeyBindings::Error; 70 return new ActionID(ids[i]); 71 } 72 else if (ids[i].context()==GLOBAL_CONTEXT) { 73 level = KeyBindings::Warning; 74 return new ActionID(ids[i]); 75 } 65 76 } 66 77 67 78 /* no conflicts */ … … 70 81 71 82 72 83 84 /* method description in header */ 85 bool KeyBindings::removeActionKey(const QString & context_name, 86 const QString & action_name, 87 const QString & key) { 88 89 ActionID id(context_name, action_name); 90 91 /* dont remove the last manditory binding */ 92 if (getManditoryBindings().contains(id)&&(actionset.getKeys(id).count()<2)) 93 return false; 94 else 95 return this->actionset.remove(id,key); 96 } 97 98 99 100 /* method description in header */ 73 101 void KeyBindings::commitAction(const ActionID & id) 74 102 { 75 103 … … 169 197 for (query.next(); query.isValid(); query.next()) 170 198 { 171 199 ActionID id(JUMP_CONTEXT, query.value(0).toString()); 172 this->actionset.addAction(id,query.value(1).toString(), 173 query.value(2).toString()); 200 201 if (query.value(1).toString().isEmpty()) 202 { 203 actionset.addAction(id, query.value(0).toString(), 204 query.value(2).toString()); 205 } 206 else actionset.addAction(id,query.value(1).toString(), 207 query.value(2).toString()); 174 208 } 175 209 } 176 210 -
mythcontrols/mythcontrols/mythcontrols.h
23 23 #ifndef MYTHCONTROLS_H 24 24 #define MYTHCONTROLS_H 25 25 26 #include <stdexcept>27 28 26 #include <mythtv/mythdialogs.h> 29 #include <mythtv/mythwidgets.h> 30 #include <mythtv/uitypes.h> 27 #include <mythtv/uilistbtntype.h> 31 28 32 29 #include "keybindings.h" 33 30 … … 47 44 * @param parent The main myth window. 48 45 * @param name The name of this window? I dunno, none of the docs 49 46 * say. 47 * @param ui_ok Will be set according to weather the UI was 48 * correctly loaded. 50 49 */ 51 MythControls(MythMainWindow *parent, const char *name=0); 50 MythControls(MythMainWindow *parent, const char *name=0, 51 bool & ui_ok=false); 52 52 53 53 /** 54 54 * @brief Delete the myth controls object. … … 56 56 ~MythControls(); 57 57 58 58 /** 59 * @brief Load up UI.60 * @return true if all UI elements were loaded successfully,61 * otherwise false it returned.62 *63 * This method grabs all of the UI "thingies" that are needed by64 * mythcontrols. If this method returns false, the plugin should65 * exit since it will probably just core dump.66 */67 bool loadUI();68 69 /**70 59 * @brief Get the currently selected context string. 71 60 * @return The currently selected context string. 72 61 * … … 85 74 protected: 86 75 87 76 /** 77 * @brief Load up UI. 78 * @return true if all UI elements were loaded successfully, 79 * otherwise false it returned. 80 * 81 * This method grabs all of the UI "thingies" that are needed by 82 * mythcontrols. If this method returns false, the plugin should 83 * exit since it will probably just core dump. 84 */ 85 bool loadUI(); 86 87 /** 88 88 * @brief The key press handler. 89 89 * @param e The key event. 90 90 */ … … 99 99 void refreshKeyInformation(); 100 100 101 101 /** 102 * @brief Launches the action menu.103 */104 void actionMenu();105 106 /**107 102 * @brief Load the settings for a particular host. 108 103 * @param hostname The host to load settings for. 109 104 */ … … 125 120 */ 126 121 size_t focusedButton(void) const; 127 122 123 /** 124 * @brief Resolve a potential conflict. 125 * @return true if the conflict should be bound, otherwise, false 126 * is returned. 127 */ 128 bool resolveConflict(ActionID *conflict, int level); 129 128 130 private slots: 129 131 130 132 /** 131 133 * @brief Add a key to the currently selected action. 132 134 */ 133 void addKeyToAction( );135 void addKeyToAction(void); 134 136 135 137 /** 136 * @brief Capture a key press using the key grabber.137 */138 void captureKey();139 140 /**141 138 * @brief Delete the currently active key. 142 139 */ 143 140 void deleteKey(); 144 141 145 142 /** 146 * @brief Kill the currently visbile popup window.147 */148 void killPopup();149 150 /**151 143 * @brief Save the settings. 152 144 */ 153 void save();145 inline void save(void) { key_bindings->commitChanges(); } 154 146 155 147 private: 156 148 157 149 UIType *focused; 158 GenericTree * context_tree; 159 UIManagedTreeListType * control_tree_list; 150 UIListTreeType *control_list; 160 151 UITextType *description; 161 152 UITextButtonType * action_buttons[Action::MAX_KEYS]; 162 153 KeyBindings *key_bindings; 163 MythPopupBox *popup;164 154 }; 165 155 166 156 -
mythcontrols/mythcontrols/keybindings.h
29 29 #include "actionid.h" 30 30 #include "actionset.h" 31 31 32 33 32 /** 34 33 * @class KeyBindings. 35 34 * @brief Information about the current keybindings. … … 43 42 public: 44 43 45 44 /** 45 * @brief Levels of conflict 46 * @li None: Does not conflict 47 * @li Potential: May conflict. 48 * @li Fatal: Frontend will become inoperable. 49 */ 50 enum ConflictLevels { Warning, Error}; 51 52 /** 46 53 * @brief Create a new KeyBindings instance. 47 54 * @param hostname The host for which to create the key bindings. 48 55 */ … … 111 118 * @brief Determine if adding a key would cause a conflict. 112 119 * @param context_name The name of the context. 113 120 * @param key The key to add. 121 * @param level The level of conflict. Check this if the return 122 * value is not NULL 114 123 * @return true if adding the key would cause a conflict. 115 124 * 116 125 * Conflicts occur if: 117 126 * @li the key is a jump point, but is bound elsewhere 118 127 * @li the key is already bound to a jumppoint. 128 * @li the key is bound to something in the global context. 119 129 * @li the key is bound to something else in the specified context 130 * 131 * If the method does not return NULL, check the value given to 132 * level. Warnings can be ignored (at the users disgression), but 133 * errors should be prevented no matter what. If they dont like it, 134 * they can learn SQL. 120 135 */ 121 136 ActionID * conflicts(const QString & context_name, 122 const QString & key ) const;137 const QString & key, int &level) const; 123 138 124 139 /** 125 140 * @brief Replace a key in an action. … … 152 167 */ 153 168 bool removeActionKey(const QString & context_name, 154 169 const QString & action_name, 155 const QString & key) { 156 return this->actionset.remove(ActionID(context_name, action_name),key); 157 } 170 const QString & key); 158 171 159 172 /** 160 173 * @brief Set the manditory bindings to their defaults. -
mythcontrols/mythcontrols/keygrabber.cpp
27 27 28 28 #include "keygrabber.h" 29 29 30 #include <mythtv/mythcontext.h> 30 31 31 32 32 33 KeyGrabPopupBox::KeyGrabPopupBox(MythMainWindow *window) … … 36 37 this->has_captured = false; 37 38 addLabel("Press A Key", Large, false); 38 39 key_label = addLabel("Waiting for key press", Small, false); 40 41 ok_button = this->addButton(tr("OK"), this, SLOT(acceptBinding())); 42 this->addButton(tr("Cancel"), this, SLOT(cancel())); 43 39 44 this->grabKeyboard(); 40 45 } 41 46 … … 82 87 /* accept events while we are capturing */ 83 88 if (this->is_capturing) e->accept(); 84 89 else MythPopupBox::keyPressEvent(e); 90 } 85 91 86 cout << QString(QKeySequence(Qt::UNICODE_ACCEL & e->key())) << endl; 92 InvalidBindingPopup::InvalidBindingPopup(MythMainWindow *window) 93 : MythPopupBox(window, "invalidbinding") 94 { 95 QString warning = "This action is manditory and needs at least one key" 96 " bound to it. Instead, try rebinding with another key."; 97 addLabel("Manditory Action", Large, false); 98 addLabel(warning, Small, true); 87 99 } 100 101 102 103 InvalidBindingPopup::InvalidBindingPopup(MythMainWindow *window, 104 const QString &action, 105 const QString &context) 106 : MythPopupBox(window, "invalidbinding") 107 { 108 QString message = "This kebinding conflicts with "; 109 message += action + " in the " + context; 110 message += " context."; 111 112 addLabel("Conflicting Binding", Large, false); 113 addLabel(message, Small, true); 114 } 115 116 117 118 OptionsMenu::OptionsMenu(MythMainWindow *window) 119 : MythPopupBox(window, "optionmenu") 120 { 121 addLabel(tr("Options"), Large, false); 122 addButton(tr("Save"), this, SLOT(save())); 123 addButton(tr("Cancel"), this, SLOT(cancel()))->setFocus(); 124 } 125 126 127 ActionMenu::ActionMenu(MythMainWindow *window) 128 : MythPopupBox(window, "actionmenu") 129 { 130 addLabel(tr("Modify Action"), Large, false); 131 addButton(tr("Set Binding"), this, SLOT(set())); 132 addButton(tr("Remove Binding"), this, SLOT(remove())); 133 addButton(tr("Cancel"), this, SLOT(cancel()))->setFocus(); 134 } 135 136 UnsavedMenu::UnsavedMenu(MythMainWindow *window) 137 : MythPopupBox(window, "unsavedmenu") 138 { 139 addLabel(tr("Unsaged Changes"), Large, false); 140 addLabel(tr("Would you like to save now?")); 141 addButton(tr("Save"), this, SLOT(save()))->setFocus(); 142 addButton(tr("Exit"), this, SLOT(cancel())); 143 } -
mythcontrols/mythcontrols/keygrabber.h
44 44 KeyGrabPopupBox(MythMainWindow * window); 45 45 46 46 /** 47 * @brief Add the OK button. 48 * @param button The button that will be hilighed once a key has 49 * been captured. 47 * @brief Get the string containing the captured key event. 50 48 */ 51 inline void addOKButton(QButton *button) { ok_button = button; }49 inline QString getCapturedKey() { return this->captured_key_event; } 52 50 51 public slots: 52 53 53 /** 54 * @brief Get the string containing the captured key event. 54 * @brief Accept the captured keybinding. 55 * 56 * The QString provided in the constructor will be set to the 57 * captured key value. 55 58 */ 56 inline QString getCapturedKeyEvent() { return this->captured_key_event; }59 inline void acceptBinding(void) { done(1); } 57 60 61 /** 62 * @brief Reject the captured key binding. 63 * 64 * The QString provided in the constructor will be set to NULL. 65 */ 66 inline void cancel(void) { done(0); } 67 58 68 protected: 59 69 60 70 /** … … 77 87 QButton *ok_button; 78 88 QLabel *key_label; 79 89 }; 90 91 92 /** 93 * @class InvalidBindingPopup 94 * @brief Tells the user that they are being bad!!! 95 */ 96 class InvalidBindingPopup : public MythPopupBox 97 { 98 Q_OBJECT; 99 100 public: 101 102 /** 103 * @brief Create a popup that explains that they are removing a 104 * critical key binding. 105 * @param window The main myth window. 106 */ 107 InvalidBindingPopup(MythMainWindow *window); 108 109 /** 110 * @brief Tell the user that the binding conflicts with another 111 * action. 112 */ 113 InvalidBindingPopup(MythMainWindow *window, const QString &action, 114 const QString &context); 115 116 /** 117 * @brief Execute the error popup 118 */ 119 inline int getOption(void) { return ExecPopup(this,SLOT(finish())); } 120 121 protected slots: 122 /** 123 * @brief Close the popup. 124 */ 125 inline void finish(void) { done(0); } 126 }; 127 128 129 /** 130 * @class OptionsMenu 131 * @brief A popup containing a list of options. 132 */ 133 class OptionsMenu : public MythPopupBox 134 { 135 136 Q_OBJECT; 137 138 public: 139 140 enum actons { SAVE, CANCEL }; 141 142 /** 143 * @brief Create a new action window. 144 */ 145 OptionsMenu(MythMainWindow *window); 146 147 /** 148 * @brief Execute the option popup. 149 */ 150 inline int getOption(void) { return ExecPopup(this,SLOT(cancel())); } 151 152 public slots: 153 154 /** 155 * @brief Slot to connect to when the save button is pressed. 156 */ 157 inline void save(void) { done(OptionsMenu::SAVE); } 158 159 /** 160 * @brief Slot to connect to when the cancel button is pressed. 161 */ 162 inline void cancel(void) { done(OptionsMenu::CANCEL); } 163 164 }; 165 166 167 168 /** 169 * @class ActionMenu 170 * @brief A popup listing ways to modify an action. 171 */ 172 class ActionMenu : public MythPopupBox 173 { 174 175 Q_OBJECT; 176 177 public: 178 179 enum actons { SET, REMOVE, CANCEL }; 180 181 /** 182 * @brief Create a new action window. 183 */ 184 ActionMenu(MythMainWindow *window); 185 186 /** 187 * @brief Execute the option popup. 188 */ 189 inline int getOption(void) { return ExecPopup(this,SLOT(cancel())); } 190 191 public slots: 192 193 /** 194 * @brief Slot to connect to when the set button is pressed. 195 */ 196 inline void set(void) { done(ActionMenu::SET); } 197 198 /** 199 * @brief Slot to connect to when the remove button is pressed. 200 */ 201 inline void remove(void) { done(ActionMenu::REMOVE); } 202 203 /** 204 * @brief Slot to connect to when the cancel button is pressed. 205 */ 206 inline void cancel(void) { done(ActionMenu::CANCEL); } 207 208 }; 209 210 /** 211 * @class OptionsMenu 212 * @brief A popup containing a list of options. 213 */ 214 class UnsavedMenu : public MythPopupBox 215 { 216 217 Q_OBJECT; 218 219 public: 220 221 enum actons { SAVE, EXIT }; 222 223 /** 224 * @brief Create a new action window. 225 */ 226 UnsavedMenu(MythMainWindow *window); 227 228 /** 229 * @brief Execute the option popup. 230 */ 231 inline int getOption(void) { return ExecPopup(this,SLOT(cancel())); } 232 233 public slots: 234 235 /** 236 * @brief Slot to connect to when the save button is pressed. 237 */ 238 inline void save(void) { done(UnsavedMenu::SAVE); } 239 240 /** 241 * @brief Slot to connect to when the cancel button is pressed. 242 */ 243 inline void cancel(void) { done(UnsavedMenu::EXIT); } 244 245 }; -
mythcontrols/mythcontrols/mythcontrols.pro
1 1 include ( ../../settings.pro ) 2 2 3 3 TEMPLATE = lib 4 CONFIG += plugin thread warn_on debug4 CONFIG += plugin thread 5 5 TARGET = mythcontrols 6 6 target.path = $${PREFIX}/lib/mythtv/plugins 7 7 INSTALLS += target -
mythcontrols/mythcontrols/main.cpp
26 26 using namespace std; 27 27 28 28 #include "mythcontrols.h" 29 #include <mythtv/mythdialogs.h> 29 30 30 31 31 32 32 /** 33 * @ name Plugin API34 * 35 * The following methods are required by all MythTV plugins.33 * @brief Initializes the plugin. 34 * @param libversion The mythtv library version. 35 * @return zero if all is well, otherwise, less than zero 36 36 */ 37 //@{ 38 extern "C" { 39 40 /** 41 * @brief Called by mythtv to initialize the plugin. 42 * @param libversion Used to make sure that the requried version of 43 * the library is being used. 44 * @return I dont really know what difference your return values makes. 45 * @todo Find out the difference this return values makes. 46 */ 47 int mythplugin_init(const char *libversion); 48 49 /** 50 * @brief Runs the plugin. 51 * @return I dont really know what difference your return values makes. 52 * @todo Find out the difference this return values makes. 53 */ 54 int mythplugin_run(void); 55 56 /** 57 * @brief Called to configure the plugin. 58 * @return I dont really know what difference your return values makes. 59 * @todo Find out the difference this return values makes. 60 */ 61 int mythplugin_config(void); 62 } 63 //@} 64 65 66 /* documented above */ 67 int mythplugin_init(const char *libversion) 37 extern "C" int mythplugin_init(const char *libversion) 68 38 { 69 39 if (!gContext->TestPopupVersion("mythcontrols", libversion, 70 40 MYTH_BINARY_VERSION)) return -1; … … 73 43 74 44 75 45 76 /* documented above */ 77 int mythplugin_run (void) 46 /** 47 * @brief Runs the plugin. 48 * @return zero if all is well, otherwise, less than zero 49 */ 50 extern "C" int mythplugin_run (void) 78 51 { 79 MythControls controls(gContext->GetMainWindow(), "controls"); 52 bool uiloaded; 53 MythMainWindow *window = gContext->GetMainWindow(); 80 54 55 /* create the keybinding plugin. uiloaded will be set to false 56 * if the theme was not correct */ 57 MythControls controls(window, "controls", uiloaded); 58 81 59 /* if the UI is successfully loaded, just giv'er*/ 82 if ( controls.loadUI())60 if (uiloaded) 83 61 { 84 62 controls.exec(); 85 63 return 0; 86 64 } 87 65 else 88 66 { 89 VERBOSE(VB_ALL, "Unable to load theme, exiting"); 67 MythPopupBox::showOkPopup(window, "Theme Error", "Could not load the " 68 "keybinding plugin's theme. Check the " 69 "console for detailed output."); 70 90 71 return -1; 91 72 } 92 73 } 93 74 94 75 95 76 96 /* documented above*/ 97 int mythplugin_config (void) { return 0; } 77 /** 78 * @brief Configures the plugin. 79 * @return zero. 80 */ 81 extern "C" int mythplugin_config (void) { return 0; } 98 82 99 83 100 84 -
mythcontrols/mythcontrols/actionset.cpp
22 22 #ifndef ACTIONSET_CPP 23 23 #define ACTIONSET_CPP 24 24 25 #include <iostream>26 27 25 #include <qmap.h> 28 26 #include <qdict.h> 29 27 #include <qvaluelist.h> … … 36 34 #include "actionset.h" 37 35 38 36 39 40 37 /* method description in header */ 41 38 bool ActionSet::add(const ActionID &id, const QString &key) 42 39 { … … 54 51 ids.push_back(id); 55 52 this->modify(id); 56 53 return true; 57 } else cerr << "Key not added" << endl;58 } else cerr << "No action" << endl;54 } 55 } 59 56 60 57 return false; 61 58 } -
mythcontrols/mythcontrols/controls-ui.xml
3 3 4 4 <window name="controls"> 5 5 6 <font name="selected" face="Arial">7 8 9 10 6 <font name="active" face="Arial"> 7 <color>#ffffff</color> 8 <size>14</size> 9 <bold>yes</bold> 10 </font> 11 11 12 <font name="active" face="Arial">13 <color>#aaaaaa</color>14 15 16 12 <font name="inactive" face="Arial"> 13 <color>#9999cc</color> 14 <size>14</size> 15 <bold>yes</bold> 16 </font> 17 17 18 <font name="inactive" face="Arial"> 19 <color>#9999cc</color> 20 <size>14</size> 21 <bold>yes</bold> 22 </font> 18 <font name="keys" face="Arial"> 19 <color>#000000</color> 20 <size>18</size> 21 <shadow>1,1</shadow> 22 <bold>yes</bold> 23 </font> 23 24 24 <font name="selectable" face="Arial"> 25 <color>#8cdeff</color> 26 <size>14</size> 27 <bold>yes</bold> 28 </font> 25 <font name="info" face="Arial"> 26 <color>#ffffff</color> 27 <size>18</size> 28 <shadow>1,1</shadow> 29 <bold>yes</bold> 30 </font> 29 31 30 <font name="labels" face="Arial">31 32 <size>16</size>33 <shadow>1,1</shadow>34 35 32 <font name="infotitle" face="Arial"> 33 <color>#ffffff</color> 34 <size>24</size> 35 <shadow>10,10</shadow> 36 <bold>yes</bold> 37 </font> 36 38 37 <font name="keys" face="Arial"> 38 <color>#000000</color> 39 <size>18</size> 40 <shadow>1,1</shadow> 41 <bold>yes</bold> 42 </font> 39 <container name="controls"> 40 <area>20,20,780,380</area> 41 <listtreearea name="controltree" draworder="0"> 42 <area>0,0,760,360</area> 43 <listsize>0,0,370,360</listsize> 44 <leveloffset>15</leveloffset> 45 <gradient type="unselected" start="#505050" end="#000000" alpha="100"/> 46 <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/> 47 <fcnfont name="active" function="active"/> 48 <fcnfont name="inactive" function="inactive"/> 49 </listtreearea> 50 </container> 43 51 44 <font name="info" face="Arial"> 45 <color>#ffffff</color> 46 <size>18</size> 47 <shadow>1,1</shadow> 48 <bold>yes</bold> 49 </font> 52 <container name="keys"> 53 <area>20,400,780,180</area> 50 54 51 < font name="infotitle" face="Arial">52 <color>#ffffff</color>53 <size>24</size>54 <shadow>10,10</shadow>55 <bold>yes</bold>56 </ font>55 <textbutton name="action_one" draworder="0"> 56 <position>20,20</position> 57 <image function="on" filename="kb-button-on.png"/> 58 <image function="off" filename="kb-button-off.png"/> 59 <font>keys</font> 60 </textbutton> 57 61 58 < font name="message" face="Arial">59 <color>#ffffff</color>60 <size>16</size>61 <shadow>1,1</shadow>62 <bold>yes</bold>63 </ font>62 <textbutton name="action_two" draworder="0"> 63 <position>200,20</position> 64 <image function="on" filename="kb-button-on.png"/> 65 <image function="off" filename="kb-button-off.png"/> 66 <font>keys</font> 67 </textbutton> 64 68 65 <container name="controls"> 66 <area>0,0,800,350</area> 69 <textbutton name="action_three" draworder="0"> 70 <position>390,20</position> 71 <image function="on" filename="kb-button-on.png"/> 72 <image function="off" filename="kb-button-off.png"/> 73 <font>keys</font> 74 </textbutton> 67 75 68 <managedtreelist name="controltree" draworder="1" bins="2"> 69 <area>0,40,800,310</area> 76 <textbutton name="action_four" draworder="0"> 77 <position>580,20</position> 78 <image function="on" filename="kb-button-on.png"/> 79 <image function="off" filename="kb-button-off.png"/> 80 <font>keys</font> 81 </textbutton> 70 82 71 <image function="selectionbar" filename="bar.png"/>72 <image function="uparrow" filename="scrollarrow-up.png"/>73 <image function="downarrow" filename="scrollarrow-dn.png"/>74 <image function="leftarrow" filename="scrollarrow-left.png"/>75 <image function="rightarrow" filename="scrollarrow-right.png"/>83 <textarea name="description" draworder="1" allign="left"> 84 <font>info</font> 85 <area>30,100,740,140</area> 86 <multiline>yes</multiline> 87 </textarea> 76 88 77 <bin number="1"> 78 <area>30,14,190,250</area> 79 <fcnfont name="active" function="active"/> 80 <fcnfont name="inactive" function="inactive"/> 81 <fcnfont name="selected" function="selected"/> 82 <fcnfont name="selectable" function="selectable"/> 83 </bin> 89 </container> 84 90 85 <bin number="2">86 <area>240,14,530,265</area>87 <fcnfont name="active" function="active"/>88 <fcnfont name="inactive" function="inactive"/>89 <fcnfont name="active" function="selected"/>90 <fcnfont name="selectable" function="selectable"/>91 </bin>92 93 </managedtreelist>94 95 <image name="showinglines" draworder="2" fleximage="yes">96 <filename>showings.png</filename>97 <position>0,0</position>98 </image>99 100 </container>101 102 <container name="keys">103 <area>0,300,800,320</area>104 105 <textarea name="infotitle" draworder="0">106 <font>infotitle</font>107 <area>282,20,236,40</area>108 <value>Key Bindings</value>109 </textarea>110 111 <textbutton name="action_one" draworder="0">112 <position>20,100</position>113 <image function="on" filename="kb-button-on.png"/>114 <image function="off" filename="kb-button-off.png"/>115 <font>keys</font>116 </textbutton>117 118 <textbutton name="action_two" draworder="0">119 <position>200,100</position>120 <image function="on" filename="kb-button-on.png"/>121 <image function="off" filename="kb-button-off.png"/>122 <font>keys</font>123 </textbutton>124 125 <textbutton name="action_three" draworder="0">126 <position>390,100</position>127 <image function="on" filename="kb-button-on.png"/>128 <image function="off" filename="kb-button-off.png"/>129 <font>keys</font>130 </textbutton>131 132 <textbutton name="action_four" draworder="0">133 <position>580,100</position>134 <image function="on" filename="kb-button-on.png"/>135 <image function="off" filename="kb-button-off.png"/>136 <font>keys</font>137 </textbutton>138 139 <image name="actionlines" draworder="1" allign="left">140 <filename>cr-lines.png</filename>141 <position>0,0</position>142 </image>143 144 <textarea name="description" draworder="1" allign="left">145 <font>info</font>146 <area>30,180,740,140</area>147 <multiline>yes</multiline>148 </textarea>149 150 151 </container>152 153 91 </window> 154 92 </mythuitheme>