MythTV  0.27pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
mythwidgets.cpp
Go to the documentation of this file.
1 #include <iostream>
2 using namespace std;
3 
4 #include <QStyle>
5 #include <QPainter>
6 #include <QCursor>
7 #include <QLayout>
8 #include <QKeyEvent>
9 #include <QHideEvent>
10 #include <QFocusEvent>
11 #include <QMouseEvent>
12 #include <QEvent>
13 
14 #include "mythwidgets.h"
15 #include "mythcontext.h"
16 #include "mythdate.h"
17 #include "mythdialogs.h"
18 #include "mythlogging.h"
19 #include "mythmainwindow.h"
20 
22 static void qt_delete(QWidgetP &widget)
23 {
24  if (widget)
25  {
26  widget->disconnect();
27  widget->hide();
28  widget->deleteLater();
29  widget = NULL;
30  }
31 }
32 
33 MythComboBox::MythComboBox(bool rw, QWidget *parent, const char *name) :
34  QComboBox(parent),
35  popup(NULL), helptext(QString::null), AcceptOnSelect(false),
36  useVirtualKeyboard(true), allowVirtualKeyboard(rw),
37  popupPosition(VKQT_POSBELOWEDIT), step(1)
38 {
39  setObjectName(name);
40  setEditable(rw);
41  useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
42 }
43 
45 {
46  Teardown();
47 }
48 
50 {
51  Teardown();
53 }
54 
56 {
58 }
59 
60 void MythComboBox::setHelpText(const QString &help)
61 {
62  bool changed = helptext != help;
63  helptext = help;
64  if (hasFocus() && changed)
65  emit changeHelpText(help);
66 }
67 
69 {
71 
74  popup->exec();
75 
77 }
78 
79 
80 void MythComboBox::keyPressEvent(QKeyEvent *e)
81 {
82  bool handled = false, updated = false;
83  QStringList actions;
84  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions,
86 
87  if ((!popup || popup->isHidden()) && !handled)
88  {
89  for (int i = 0; i < actions.size() && !handled; i++)
90  {
91  QString action = actions[i];
92  handled = true;
93 
94  if (action == "UP")
95  {
96  focusNextPrevChild(false);
97  }
98  else if (action == "DOWN")
99  {
100  focusNextPrevChild(true);
101  }
102  else if (action == "LEFT")
103  {
104  if (currentIndex() == 0)
105  setCurrentIndex(count()-1);
106  else if (count() > 0)
107  setCurrentIndex((currentIndex() - 1) % count());
108  updated = true;
109  }
110  else if (action == "RIGHT")
111  {
112  if (count() > 0)
113  setCurrentIndex((currentIndex() + 1) % count());
114  updated = true;
115  }
116  else if (action == "PAGEDOWN")
117  {
118  if (currentIndex() == 0)
119  setCurrentIndex(count() - (step % count()));
120  else if (count() > 0)
121  setCurrentIndex(
122  (currentIndex() + count() - (step % count())) % count());
123  updated = true;
124  }
125  else if (action == "PAGEUP")
126  {
127  if (count() > 0)
128  setCurrentIndex(
129  (currentIndex() + (step % count())) % count());
130  updated = true;
131  }
132  else if (action == "SELECT" && AcceptOnSelect)
133  emit accepted(currentIndex());
134  else if (action == "SELECT" &&
135  (e->text().isEmpty() ||
136  (e->key() == Qt::Key_Enter) ||
137  (e->key() == Qt::Key_Return) ||
138  (e->key() == Qt::Key_Space)))
139  {
142  else
143  handled = true;
144  }
145 
146  else
147  handled = false;
148  }
149  }
150 
151  if (updated)
152  {
153  emit activated(currentIndex());
154  emit activated(itemText(currentIndex()));
155  }
156  if (!handled)
157  {
158  if (isEditable())
160  else
161  e->ignore();
162  }
163 }
164 
165 void MythComboBox::focusInEvent(QFocusEvent *e)
166 {
167  emit changeHelpText(helptext);
168  emit gotFocus();
169 
170  QColor highlight = palette().color(QPalette::Highlight);
171 
172  QPalette palette;
173  palette.setColor(backgroundRole(), highlight);
174  setPalette(palette);
175 
176  if (lineEdit())
177  lineEdit()->setPalette(palette);
178 
180 }
181 
182 void MythComboBox::focusOutEvent(QFocusEvent *e)
183 {
184  setPalette(QPalette());
185 
186  if (lineEdit())
187  {
188  lineEdit()->setPalette(QPalette());
189 
190  // commit change if the user was editing an entry
191  QString curText = currentText();
192  int i;
193  bool foundItem = false;
194 
195  for(i = 0; i < count(); i++)
196  if (curText == itemText(i))
197  foundItem = true;
198 
199  if (!foundItem)
200  {
201  insertItem(curText);
202  setCurrentIndex(count()-1);
203  }
204  }
205 
207 }
208 
209 void MythCheckBox::keyPressEvent(QKeyEvent* e)
210 {
211  bool handled = false;
212  QStringList actions;
213 
214  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
215 
216  for ( int i = 0; i < actions.size() && !handled; i++)
217  {
218  QString action = actions[i];
219  handled = true;
220 
221  if (action == "UP")
222  focusNextPrevChild(false);
223  else if (action == "DOWN")
224  focusNextPrevChild(true);
225  else if (action == "LEFT" || action == "RIGHT" || action == "SELECT")
226  toggle();
227  else
228  handled = false;
229  }
230 
231  if (!handled)
232  e->ignore();
233 }
234 
235 void MythCheckBox::setHelpText(const QString &help)
236 {
237  bool changed = helptext != help;
238  helptext = help;
239  if (hasFocus() && changed)
240  emit changeHelpText(help);
241 }
242 
243 void MythCheckBox::focusInEvent(QFocusEvent *e)
244 {
245  emit changeHelpText(helptext);
246 
247  QColor highlight = palette().color(QPalette::Highlight);
248  QPalette palette;
249  palette.setColor(backgroundRole(), highlight);
250  setPalette(palette);
251 
253 }
254 
255 void MythCheckBox::focusOutEvent(QFocusEvent *e)
256 {
257  setPalette(QPalette());
259 }
260 
262 {
263  bool handled = false;
264  QStringList actions;
265  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
266 
267  for (int i = 0; i < actions.size() && !handled; i++)
268  {
269  QString action = actions[i];
270  handled = true;
271 
272  if (action == "UP")
273  focusNextPrevChild(false);
274  else if (action == "DOWN")
275  focusNextPrevChild(true);
276  else if (action == "LEFT" || action == "RIGHT")
277  toggle();
278  else
279  handled = false;
280  }
281 
282  if (!handled)
283  e->ignore();
284 }
285 
286 void MythRadioButton::setHelpText(const QString &help)
287 {
288  bool changed = helptext != help;
289  helptext = help;
290  if (hasFocus() && changed)
291  emit changeHelpText(help);
292 }
293 
294 void MythRadioButton::focusInEvent(QFocusEvent *e)
295 {
296  emit changeHelpText(helptext);
297 
298  QColor highlight = palette().color(QPalette::Highlight);
299 
300  QPalette palette;
301  palette.setColor(backgroundRole(), highlight);
302  setPalette(palette);
303 
305 }
306 
307 void MythRadioButton::focusOutEvent(QFocusEvent *e)
308 {
309  setPalette(QPalette());
311 }
312 
313 
314 void MythSpinBox::setHelpText(const QString &help)
315 {
316  bool changed = helptext != help;
317  helptext = help;
318  if (hasFocus() && changed)
319  emit changeHelpText(help);
320 }
321 
322 void MythSpinBox::keyPressEvent(QKeyEvent* e)
323 {
324  bool handled = false;
325  QStringList actions;
326  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
327 
328  for (int i = 0; i < actions.size() && !handled; i++)
329  {
330  QString action = actions[i];
331  handled = true;
332 
333  if (action == "UP")
334  focusNextPrevChild(false);
335  else if (action == "DOWN")
336  focusNextPrevChild(true);
337  else if (action == "LEFT")
338  allowsinglestep ? setValue(value()-1) : stepDown();
339  else if (action == "RIGHT")
340  allowsinglestep ? setValue(value()+1) : stepUp();
341  else if (action == "PAGEDOWN")
342  stepDown();
343  else if (action == "PAGEUP")
344  stepUp();
345  else if (action == "SELECT")
346  handled = true;
347  else
348  handled = false;
349  }
350 
351  if (!handled)
353 }
354 
355 void MythSpinBox::focusInEvent(QFocusEvent *e)
356 {
357  emit changeHelpText(helptext);
358 
359  QColor highlight = palette().color(QPalette::Highlight);
360 
361  QPalette palette;
362  palette.setColor(backgroundRole(), highlight);
363  setPalette(palette);
364 
366 }
367 
368 void MythSpinBox::focusOutEvent(QFocusEvent *e)
369 {
370  setPalette(QPalette());
372 }
373 
374 void MythSlider::keyPressEvent(QKeyEvent* e)
375 {
376  bool handled = false;
377  QStringList actions;
378  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
379 
380  for (int i = 0; i < actions.size() && !handled; i++)
381  {
382  QString action = actions[i];
383  handled = true;
384 
385  if (action == "UP")
386  focusNextPrevChild(false);
387  else if (action == "DOWN")
388  focusNextPrevChild(true);
389  else if (action == "LEFT")
390  setValue(value() - singleStep());
391  else if (action == "RIGHT")
392  setValue(value() + singleStep());
393  else if (action == "SELECT")
394  handled = true;
395  else
396  handled = false;
397  }
398 
399  if (!handled)
401 }
402 
403 void MythSlider::setHelpText(const QString &help)
404 {
405  bool changed = helptext != help;
406  helptext = help;
407  if (hasFocus() && changed)
408  emit changeHelpText(help);
409 }
410 
411 void MythSlider::focusInEvent(QFocusEvent *e)
412 {
413  emit changeHelpText(helptext);
414 
415  QColor highlight = palette().color(QPalette::Highlight);
416 
417  QPalette palette;
418  palette.setColor(backgroundRole(), highlight);
419  setPalette(palette);
420 
422 }
423 
424 void MythSlider::focusOutEvent(QFocusEvent *e)
425 {
426  setPalette(QPalette());
428 }
429 
430 MythLineEdit::MythLineEdit(QWidget *parent, const char *name) :
431  QLineEdit(parent),
432  popup(NULL), helptext(QString::null), rw(true),
433  useVirtualKeyboard(true),
434  allowVirtualKeyboard(true),
435  popupPosition(VKQT_POSBELOWEDIT)
436 {
437  setObjectName(name);
438  useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
439 }
440 
442  const QString &contents, QWidget *parent, const char *name) :
443  QLineEdit(contents, parent),
444  popup(NULL), helptext(QString::null), rw(true),
445  useVirtualKeyboard(true),
446  allowVirtualKeyboard(true),
447  popupPosition(VKQT_POSBELOWEDIT)
448 {
449  setObjectName(name);
450  useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
451 }
452 
454 {
455  Teardown();
456 }
457 
459 {
460  Teardown();
462 }
463 
465 {
466  qt_delete(popup);
467 }
468 
470 {
471  qt_delete(popup);
472 
475  popup->exec();
476 
477  qt_delete(popup);
478 }
479 
480 void MythLineEdit::keyPressEvent(QKeyEvent *e)
481 {
482  bool handled = false;
483  QStringList actions;
484  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions, false);
485 
486  if ((!popup || popup->isHidden()) && !handled)
487  {
488  for (int i = 0; i < actions.size() && !handled; i++)
489  {
490  QString action = actions[i];
491  handled = true;
492 
493  if (action == "UP")
494  focusNextPrevChild(false);
495  else if (action == "DOWN")
496  focusNextPrevChild(true);
497  else if (action == "SELECT" &&
498  (e->text().isEmpty() ||
499  (e->key() == Qt::Key_Enter) ||
500  (e->key() == Qt::Key_Return)))
501  {
504  else
505  handled = false;
506  }
507  else if (action == "SELECT" && e->text().isEmpty() )
508  e->ignore();
509  else
510  handled = false;
511  }
512  }
513 
514  if (!handled)
515  if (rw || e->key() == Qt::Key_Escape || e->key() == Qt::Key_Left
516  || e->key() == Qt::Key_Return || e->key() == Qt::Key_Right)
517  QLineEdit::keyPressEvent(e);
518 }
519 
520 void MythLineEdit::setText(const QString &text)
521 {
522  // Don't mess with the cursor position; it causes
523  // counter-intuitive behaviour due to interactions with the
524  // communication with the settings stuff
525 
526  int pos = cursorPosition();
527  QLineEdit::setText(text);
528  setCursorPosition(pos);
529 }
530 
531 QString MythLineEdit::text(void)
532 {
533  return QLineEdit::text();
534 }
535 
536 void MythLineEdit::setHelpText(const QString &help)
537 {
538  bool changed = helptext != help;
539  helptext = help;
540  if (hasFocus() && changed)
541  emit changeHelpText(help);
542 }
543 
544 void MythLineEdit::focusInEvent(QFocusEvent *e)
545 {
546  emit changeHelpText(helptext);
547 
548  QColor highlight = palette().color(QPalette::Highlight);
549 
550  QPalette palette;
551  palette.setColor(backgroundRole(), highlight);
552  setPalette(palette);
553 
555 }
556 
557 void MythLineEdit::focusOutEvent(QFocusEvent *e)
558 {
559  setPalette(QPalette());
560  if (popup && !popup->isHidden() && !popup->hasFocus())
561  popup->hide();
563 }
564 
565 void MythLineEdit::hideEvent(QHideEvent *e)
566 {
567  if (popup && !popup->isHidden())
568  popup->hide();
570 }
571 
573 {
575 }
576 
577 MythRemoteLineEdit::MythRemoteLineEdit(QWidget * parent, const char *name) :
578  QTextEdit(parent)
579 {
580  setObjectName(name);
581  my_font = NULL;
582  m_lines = 1;
583  this->Init();
584 }
585 
586 MythRemoteLineEdit::MythRemoteLineEdit(const QString & contents,
587  QWidget * parent, const char *name) :
588  QTextEdit(parent)
589 {
590  setObjectName(name);
591  my_font = NULL;
592  m_lines = 1;
593  this->Init();
594  setText(contents);
595 }
596 
597 MythRemoteLineEdit::MythRemoteLineEdit(QFont *a_font, QWidget * parent,
598  const char *name) :
599  QTextEdit(parent)
600 {
601  setObjectName(name);
602  my_font = a_font;
603  m_lines = 1;
604  this->Init();
605 }
606 
607 MythRemoteLineEdit::MythRemoteLineEdit(int lines, QWidget * parent,
608  const char *name) :
609  QTextEdit(parent)
610 {
611  setObjectName(name);
612  my_font = NULL;
613  m_lines = lines;
614  this->Init();
615 }
616 
618 {
619  // Bunch of default values
620  cycle_timer = new QTimer();
621  shift = false;
622  active_cycle = false;
623  current_choice = "";
624  current_set = "";
625 
626  cycle_time = 3000;
627 
630 
632  QColor(100, 100, 100), QColor(0, 255, 255), QColor(255, 0, 0));
633 
634  // Try and make sure it doesn't ever change
635  setWordWrapMode(QTextOption::NoWrap);
636 
637  if (my_font)
638  setFont(*my_font);
639 
640  QFontMetrics fontsize(font());
641 
642  setMinimumHeight(fontsize.height() * 5 / 4);
643  setMaximumHeight(fontsize.height() * m_lines * 5 / 4);
644 
645  connect(cycle_timer, SIGNAL(timeout()), this, SLOT(endCycle()));
646 
647  popup = NULL;
648  useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
650 }
651 
652 
654  QColor unselected, QColor selected, QColor special)
655 {
656  col_unselected = unselected;
657  hex_unselected = QString("%1%2%3")
658  .arg(col_unselected.red(), 2, 16, QLatin1Char('0'))
659  .arg(col_unselected.green(), 2, 16, QLatin1Char('0'))
660  .arg(col_unselected.blue(), 2, 16, QLatin1Char('0'));
661 
662  col_selected = selected;
663  hex_selected = QString("%1%2%3")
664  .arg(col_selected.red(), 2, 16, QLatin1Char('0'))
665  .arg(col_selected.green(), 2, 16, QLatin1Char('0'))
666  .arg(col_selected.blue(), 2, 16, QLatin1Char('0'));
667 
668  col_special = special;
669  hex_special = QString("%1%2%3")
670  .arg(col_special.red(), 2, 16, QLatin1Char('0'))
671  .arg(col_special.green(), 2, 16, QLatin1Char('0'))
672  .arg(col_special.blue(), 2, 16, QLatin1Char('0'));
673 }
674 
675 void MythRemoteLineEdit::startCycle(QString current_choice, QString set)
676 {
677  if (active_cycle)
678  {
679  LOG(VB_GENERAL, LOG_ALERT,
680  "startCycle() called, but edit is already in a cycle.");
681  return;
682  }
683 
684  cycle_timer->setSingleShot(true);
685  cycle_timer->start(cycle_time);
686  active_cycle = true;
687 
688  QTextCursor pre_cycle_cursor = textCursor();
689 
690  QTextCursor upto_cursor_sel = pre_cycle_cursor;
691  upto_cursor_sel.movePosition(
692  QTextCursor::NoMove, QTextCursor::MoveAnchor);
693  upto_cursor_sel.movePosition(
694  QTextCursor::Start, QTextCursor::KeepAnchor);
695  pre_cycle_text_before_cursor = upto_cursor_sel.selectedText();
696 
697  QTextCursor from_cursor_sel = pre_cycle_cursor;
698  from_cursor_sel.movePosition(
699  QTextCursor::NoMove, QTextCursor::MoveAnchor);
700  from_cursor_sel.movePosition(
701  QTextCursor::End, QTextCursor::KeepAnchor);
702  pre_cycle_text_after_cursor = from_cursor_sel.selectedText();
703 
705 
706  updateCycle(current_choice, set); // Show the user their options
707 }
708 
709 void MythRemoteLineEdit::updateCycle(QString current_choice, QString set)
710 {
711  int index;
712  QString aString, bString;
713 
714  // Show the characters in the current set being cycled
715  // through, with the current choice in a different color. If the current
716  // character is uppercase X (interpreted as destructive
717  // backspace) or an underscore (interpreted as a space)
718  // then show these special cases in yet another color.
719 
720  if (shift)
721  {
722  set = set.toUpper();
723  current_choice = current_choice.toUpper();
724  }
725 
726  bString = "<B>";
727  if (current_choice == "_" || current_choice == "X")
728  {
729  bString += "<FONT COLOR=\"#";
730  bString += hex_special;
731  bString += "\">";
732  bString += current_choice;
733  bString += "</FONT>";
734  }
735  else
736  {
737  bString += "<FONT COLOR=\"#";
738  bString += hex_selected;
739  bString += "\">";
740  bString += current_choice;
741  bString += "</FONT>";
742  }
743  bString += "</B>";
744 
745  index = set.indexOf(current_choice);
746  int length = set.length();
747  if (index < 0 || index > length)
748  {
749  LOG(VB_GENERAL, LOG_ALERT,
750  QString("MythRemoteLineEdit passed a choice of \"%1"
751  "\" which is not in set \"%2\"")
752  .arg(current_choice).arg(set));
753  setText("????");
754  return;
755  }
756  else
757  {
758  set.replace(index, current_choice.length(), bString);
759  }
760 
761  QString esc_upto = pre_cycle_text_before_cursor;
762  QString esc_from = pre_cycle_text_after_cursor;
763 
764  esc_upto.replace("<", "&lt;").replace(">", "&gt;").replace("\n", "<br>");
765  esc_from.replace("<", "&lt;").replace(">", "&gt;").replace("\n", "<br>");
766 
767  aString = esc_upto;
768  aString += "<FONT COLOR=\"#";
769  aString += hex_unselected;
770  aString += "\">[";
771  aString += set;
772  aString += "]</FONT>";
773  aString += esc_from;
774  setHtml(aString);
775 
776  QTextCursor tmp = textCursor();
777  tmp.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
778  tmp.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor,
779  pre_cycle_pos + set.length());
780  setTextCursor(tmp);
781  update();
782 
783  if (current_choice == "X" && !pre_cycle_text_before_cursor.isEmpty())
784  {
785  // If current selection is delete, select the character to be deleted
786  QTextCursor tmp = textCursor();
787  tmp.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
788  tmp.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor,
789  pre_cycle_pos - 1);
790  tmp.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
791  setTextCursor(tmp);
792  }
793  else
794  {
795  // Restore original cursor location
796  QTextCursor tmp = textCursor();
797  tmp.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
798  tmp.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor,
799  pre_cycle_pos);
800  setTextCursor(tmp);
801  }
802 }
803 
805 {
806  if (!active_cycle)
807  return;
808 
809  QString tmpString = "";
810  int pos = pre_cycle_pos;
811 
812  // The timer ran out or the user pressed a key
813  // outside of the current set of choices
814  if (!select)
815  {
816  tmpString = pre_cycle_text_before_cursor;
817  }
818  else if (current_choice == "X") // destructive backspace
819  {
820  if (!pre_cycle_text_before_cursor.isEmpty())
821  {
822  tmpString = pre_cycle_text_before_cursor.left(
823  pre_cycle_text_before_cursor.length() - 1);
824  pos--;
825  }
826  }
827  else
828  {
829  current_choice = (current_choice == "_") ? " " : current_choice;
831 
832  tmpString = pre_cycle_text_before_cursor;
833  tmpString += current_choice;
834  pos++;
835  }
836 
837  tmpString += pre_cycle_text_after_cursor;
838 
839  setPlainText(tmpString);
840 
841  QTextCursor tmpCursor = textCursor();
842  tmpCursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
843  tmpCursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, pos);
844  setTextCursor(tmpCursor);
845 
846  active_cycle = false;
847  current_choice = "";
848  current_set = "";
851 
852  if (select)
853  emit textChanged(toPlainText());
854 }
855 
856 void MythRemoteLineEdit::setText(const QString &text)
857 {
859  QTextEdit::insertPlainText(text);
860 }
861 
863 {
864  return QTextEdit::toPlainText();
865 }
866 
868 {
869  bool handled = false;
870  QStringList actions;
871  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions, false);
872 
873  if ((!popup || popup->isHidden()) && !handled)
874  {
875  for (int i = 0; i < actions.size() && !handled; i++)
876  {
877  QString action = actions[i];
878  handled = true;
879 
880  if (action == "UP")
881  {
882  endCycle();
883  // Need to call very base one because
884  // QTextEdit reimplements it to tab
885  // through links (even if you're in
886  // PlainText Mode !!)
887  QWidget::focusNextPrevChild(false);
888  emit tryingToLooseFocus(false);
889  }
890  else if (action == "DOWN")
891  {
892  endCycle();
893  QWidget::focusNextPrevChild(true);
894  emit tryingToLooseFocus(true);
895  }
896  else if ((action == "SELECT") &&
897  (!active_cycle) &&
898  ((e->text().isEmpty()) ||
899  (e->key() == Qt::Key_Enter) ||
900  (e->key() == Qt::Key_Return)))
901  {
902  if (useVirtualKeyboard)
904  }
905  else if ((action == "ESCAPE") && active_cycle)
906  {
907  endCycle(false);
908  }
909  else
910  handled = false;
911  }
912  }
913 
914  if (handled)
915  return;
916 
917  if (popup && !popup->isHidden())
918  {
919  endCycle();
921  emit textChanged(toPlainText());
922  return;
923  }
924 
925  switch (e->key())
926  {
927  case Qt::Key_Enter:
928  case Qt::Key_Return:
929  handled = true;
930  endCycle();
931  e->ignore();
932  break;
933 
934  // Only eat Qt::Key_Space if we are in a cycle
935 
936  case Qt::Key_Space:
937  if (active_cycle)
938  {
939  handled = true;
940  endCycle();
941  e->ignore();
942  }
943  break;
944 
945  // If you want to mess around with other ways to allocate
946  // key presses you can just add entries between the quotes
947 
948  case Qt::Key_1:
949  cycleKeys("_X%-/.?()1");
950  handled = true;
951  break;
952 
953  case Qt::Key_2:
954  cycleKeys("abc2");
955  handled = true;
956  break;
957 
958  case Qt::Key_3:
959  cycleKeys("def3");
960  handled = true;
961  break;
962 
963  case Qt::Key_4:
964  cycleKeys("ghi4");
965  handled = true;
966  break;
967 
968  case Qt::Key_5:
969  cycleKeys("jkl5");
970  handled = true;
971  break;
972 
973  case Qt::Key_6:
974  cycleKeys("mno6");
975  handled = true;
976  break;
977 
978  case Qt::Key_7:
979  cycleKeys("pqrs7");
980  handled = true;
981  break;
982 
983  case Qt::Key_8:
984  cycleKeys("tuv8");
985  handled = true;
986  break;
987 
988  case Qt::Key_9:
989  cycleKeys("wxyz90");
990  handled = true;
991  break;
992 
993  case Qt::Key_0:
994  toggleShift();
995  handled = true;
996  break;
997  }
998 
999  if (!handled)
1000  {
1001  endCycle();
1003  emit textChanged(toPlainText());
1004  }
1005 }
1006 
1007 void MythRemoteLineEdit::setCycleTime(float desired_interval)
1008 {
1009  if (desired_interval < 0.5 || desired_interval > 10.0)
1010  {
1011  LOG(VB_GENERAL, LOG_ALERT,
1012  QString("cycle interval of %1 milliseconds ")
1013  .arg((int) (desired_interval * 1000)) +
1014  "\n\t\t\tis outside of the allowed range of "
1015  "500 to 10,000 milliseconds");
1016  return;
1017  }
1018 
1019  cycle_time = (int) (desired_interval * 1000);
1020 }
1021 
1022 void MythRemoteLineEdit::cycleKeys(QString cycle_list)
1023 {
1024  int index;
1025 
1026  if (active_cycle)
1027  {
1028  if (cycle_list == current_set)
1029  {
1030  // Regular movement through existing set
1031  cycle_timer->start(cycle_time);
1032  index = current_set.indexOf(current_choice);
1033  int length = current_set.length();
1034  if (index + 1 >= length)
1035  {
1036  index = -1;
1037  }
1038  current_choice = current_set.mid(index + 1, 1);
1040  }
1041  else
1042  {
1043  // Previous cycle was still active, but user moved
1044  // to another keypad key
1045  endCycle();
1046  current_choice = cycle_list.left(1);
1047  current_set = cycle_list;
1048  cycle_timer->start(cycle_time);
1050  }
1051  }
1052  else
1053  {
1054  // First press with no cycle of any type active
1055  current_choice = cycle_list.left(1);
1056  current_set = cycle_list;
1058  }
1059 }
1060 
1062 {
1063  // Toggle uppercase/lowercase and
1064  // update the cycle display if it's
1065  // active
1066  QString temp_choice = current_choice;
1067  QString temp_set = current_set;
1068 
1069  if (shift)
1070  {
1071  shift = false;
1072  }
1073  else
1074  {
1075  shift = true;
1076  temp_choice = current_choice.toUpper();
1077  temp_set = current_set.toUpper();
1078  }
1079  if (active_cycle)
1080  {
1081  updateCycle(temp_choice, temp_set);
1082  }
1083 }
1084 
1086 {
1087  bool changed = helptext != help;
1088  helptext = help;
1089  if (hasFocus() && changed)
1090  emit changeHelpText(help);
1091 }
1092 
1094 {
1095  emit changeHelpText(helptext);
1096  emit gotFocus(); //perhaps we need to save a playlist?
1097 
1098  QColor highlight = palette().color(QPalette::Highlight);
1099 
1100  QPalette palette;
1101  palette.setColor(backgroundRole(), highlight);
1102  setPalette(palette);
1103 
1105 }
1106 
1108 {
1109  setPalette(QPalette());
1110 
1111  if (popup && !popup->isHidden() && !popup->hasFocus())
1112  popup->hide();
1113 
1114  emit lostFocus();
1116 }
1117 
1119 {
1120  Teardown();
1121 }
1122 
1124 {
1125  Teardown();
1127 }
1128 
1130 {
1131  if (cycle_timer)
1132  {
1133  cycle_timer->disconnect();
1134  cycle_timer->deleteLater();
1135  cycle_timer = NULL;
1136  }
1137 
1138  qt_delete(popup);
1139 }
1140 
1142 {
1143  qt_delete(popup);
1144 
1145  popup = new VirtualKeyboardQt(GetMythMainWindow(), this);
1147  popup->exec();
1148 
1149  qt_delete(popup);
1150 }
1151 
1152 void MythRemoteLineEdit::insert(QString text)
1153 {
1154  QTextEdit::insertPlainText(text);
1155  emit textChanged(toPlainText());
1156 }
1157 
1159 {
1160  textCursor().deleteChar();
1161  emit textChanged(toPlainText());
1162 }
1163 
1165 {
1166  textCursor().deletePreviousChar();
1167  emit textChanged(toPlainText());
1168 }
1169 
1170 MythPushButton::MythPushButton(const QString &ontext, const QString &offtext,
1171  QWidget *parent, bool isOn)
1172  : QPushButton(ontext, parent)
1173 {
1174  onText = ontext;
1175  offText = offtext;
1176 
1177  setCheckable(true);
1178 
1179  if (isOn)
1180  setText(onText);
1181  else
1182  setText(offText);
1183 
1184  setChecked(isOn);
1185 }
1186 
1187 void MythPushButton::setHelpText(const QString &help)
1188 {
1189  bool changed = helptext != help;
1190  helptext = help;
1191  if (hasFocus() && changed)
1192  emit changeHelpText(help);
1193 }
1194 
1196 {
1197  bool handled = false;
1198  QStringList actions;
1199  keyPressActions.clear();
1200 
1201  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
1202 
1203  if (!handled && !actions.isEmpty())
1204  {
1205  keyPressActions = actions;
1206 
1207  for (int i = 0; i < actions.size() && !handled; i++)
1208  {
1209  QString action = actions[i];
1210  if (action == "SELECT")
1211  {
1212  if (isCheckable())
1213  toggleText();
1214  setDown(true);
1215  emit pressed();
1216  handled = true;
1217  }
1218  }
1219  }
1220 
1221  if (!handled)
1223 }
1224 
1226 {
1227  bool handled = false;
1228  QStringList actions = keyPressActions;
1229  for (int i = 0; i < actions.size() && !handled; i++)
1230  {
1231  QString action = actions[i];
1232  if (action == "SELECT")
1233  {
1234  QKeyEvent tempe(QEvent::KeyRelease, Qt::Key_Space,
1235  Qt::NoModifier, " ");
1237  handled = true;
1238  }
1239  }
1240 
1241  if (!handled)
1243 }
1244 
1246 {
1247  if (!isCheckable())
1248  return;
1249 
1250  if (isChecked())
1251  setText(offText);
1252  else
1253  setText(onText);
1254 }
1255 
1256 void MythPushButton::focusInEvent(QFocusEvent *e)
1257 {
1258  emit changeHelpText(helptext);
1259 
1260  QColor highlight = palette().color(QPalette::Highlight);
1261  QPalette palette;
1262  palette.setColor(backgroundRole(), highlight);
1263  setPalette(palette);
1264 
1266 }
1267 
1268 void MythPushButton::focusOutEvent(QFocusEvent *e)
1269 {
1270  setPalette(QPalette());
1272 }
1273 
1274 MythListBox::MythListBox(QWidget *parent, const QString &name) :
1275  QListWidget(parent)
1276 {
1277  setObjectName(name);
1278  connect(this, SIGNAL(itemSelectionChanged()),
1279  this, SLOT(HandleItemSelectionChanged()));
1280 }
1281 
1283 {
1285 
1286  QPalette pal = palette();
1287  QPalette::ColorRole nR = QPalette::Highlight;
1288  QPalette::ColorGroup oA = QPalette::Active;
1289  QPalette::ColorRole oR = QPalette::Button;
1290  pal.setColor(QPalette::Active, nR, pal.color(oA,oR));
1291  pal.setColor(QPalette::Inactive, nR, pal.color(oA,oR));
1292  pal.setColor(QPalette::Disabled, nR, pal.color(oA,oR));
1293 
1294  const_cast<MythListBox*>(this)->setPalette(pal);
1295 }
1296 
1297 void MythListBox::setCurrentItem(const QString& matchText, bool caseSensitive,
1298  bool partialMatch)
1299 {
1300  for (unsigned i = 0 ; i < (unsigned)count() ; ++i)
1301  {
1302  if (partialMatch)
1303  {
1304  if (caseSensitive)
1305  {
1306  if (text(i).startsWith(matchText))
1307  {
1308  setCurrentRow(i);
1309  break;
1310  }
1311  }
1312  else
1313  {
1314  if (text(i).toLower().startsWith(matchText.toLower()))
1315  {
1316  setCurrentRow(i);
1317  break;
1318  }
1319  }
1320  }
1321  else
1322  {
1323  if (caseSensitive)
1324  {
1325  if (text(i) == matchText)
1326  {
1327  setCurrentRow(i);
1328  break;
1329  }
1330  }
1331  else
1332  {
1333  if (text(i).toLower() == matchText.toLower())
1334  {
1335  setCurrentRow(i);
1336  break;
1337  }
1338  }
1339  }
1340  }
1341 }
1342 
1344 {
1345  QList<QListWidgetItem*> items = QListWidget::selectedItems();
1346  int row = getIndex(items);
1347  if (row >= 0)
1348  emit highlighted(row);
1349 }
1350 
1351 void MythListBox::keyPressEvent(QKeyEvent* e)
1352 {
1353  bool handled = false;
1354  QStringList actions;
1355  handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
1356 
1357  for (int i = 0; i < actions.size() && !handled; i++)
1358  {
1359  QString action = actions[i];
1360  if (action == "UP" || action == "DOWN" || action == "PAGEUP" ||
1361  action == "PAGEDOWN" || action == "LEFT" || action == "RIGHT")
1362  {
1363  int key;
1364  if (action == "UP")
1365  {
1366  // Qt::Key_Up at top of list allows focus to move to other widgets
1367  if (currentItem() == 0)
1368  {
1369  focusNextPrevChild(false);
1370  handled = true;
1371  continue;
1372  }
1373 
1374  key = Qt::Key_Up;
1375  }
1376  else if (action == "DOWN")
1377  {
1378  // Qt::Key_down at bottom of list allows focus to move to other widgets
1379  if (currentRow() == (int) count() - 1)
1380  {
1381  focusNextPrevChild(true);
1382  handled = true;
1383  continue;
1384  }
1385 
1386  key = Qt::Key_Down;
1387  }
1388  else if (action == "LEFT")
1389  {
1390  focusNextPrevChild(false);
1391  handled = true;
1392  continue;
1393  }
1394  else if (action == "RIGHT")
1395  {
1396  focusNextPrevChild(true);
1397  handled = true;
1398  continue;
1399  }
1400  else if (action == "PAGEUP")
1401  key = Qt::Key_PageUp;
1402  else if (action == "PAGEDOWN")
1403  key = Qt::Key_PageDown;
1404  else
1405  key = Qt::Key_unknown;
1406 
1407  QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier);
1409  handled = true;
1410  }
1411  else if (action == "0" || action == "1" || action == "2" ||
1412  action == "3" || action == "4" || action == "5" ||
1413  action == "6" || action == "7" || action == "8" ||
1414  action == "9")
1415  {
1416  int percent = action.toInt() * 10;
1417  int nextItem = percent * count() / 100;
1418  if (!itemVisible(nextItem))
1419  setTopRow(nextItem);
1420  setCurrentRow(nextItem);
1421  handled = true;
1422  }
1423  else if (action == "PREVVIEW")
1424  {
1425  int nextItem = currentRow();
1426  if (nextItem > 0)
1427  nextItem--;
1428  while (nextItem > 0 && text(nextItem)[0] == ' ')
1429  nextItem--;
1430  if (!itemVisible(nextItem))
1431  setTopRow(nextItem);
1432  setCurrentRow(nextItem);
1433  handled = true;
1434  }
1435  else if (action == "NEXTVIEW")
1436  {
1437  int nextItem = currentRow();
1438  if (nextItem < (int)count() - 1)
1439  nextItem++;
1440  while (nextItem < (int)count() - 1 && text(nextItem)[0] == ' ')
1441  nextItem++;
1442  if (!itemVisible(nextItem))
1443  setTopRow(nextItem);
1444  setCurrentRow(nextItem);
1445  handled = true;
1446  }
1447  else if (action == "MENU")
1448  emit menuButtonPressed(currentRow());
1449  else if (action == "EDIT")
1450  emit editButtonPressed(currentRow());
1451  else if (action == "DELETE")
1452  emit deleteButtonPressed(currentRow());
1453  else if (action == "SELECT")
1454  emit accepted(currentRow());
1455  }
1456 
1457  if (!handled)
1458  e->ignore();
1459 }
1460 
1461 void MythListBox::setHelpText(const QString &help)
1462 {
1463  bool changed = helptext != help;
1464  helptext = help;
1465  if (hasFocus() && changed)
1466  emit changeHelpText(help);
1467 }
1468 
1469 void MythListBox::focusOutEvent(QFocusEvent *e)
1470 {
1471  QPalette pal = palette();
1472  QPalette::ColorRole nR = QPalette::Highlight;
1473  QPalette::ColorGroup oA = QPalette::Active;
1474  QPalette::ColorRole oR = QPalette::Button;
1475  pal.setColor(QPalette::Active, nR, pal.color(oA,oR));
1476  pal.setColor(QPalette::Inactive, nR, pal.color(oA,oR));
1477  pal.setColor(QPalette::Disabled, nR, pal.color(oA,oR));
1478  setPalette(pal);
1480 }
1481 
1482 void MythListBox::focusInEvent(QFocusEvent *e)
1483 {
1484  setPalette(QPalette());
1485 
1486  emit changeHelpText(helptext);
1488 }
1489 
1490 
1492 {
1493  QListWidgetItem *widget = item(row);
1494  if (widget)
1495  scrollToItem(widget, QAbstractItemView::PositionAtTop);
1496 }
1497 
1498 void MythListBox::insertItem(const QString &label)
1499 {
1500  addItem(label);
1501 }
1502 
1503 void MythListBox::insertStringList(const QStringList &label_list)
1504 {
1505  addItems(label_list);
1506 }
1507 
1509 {
1510  QListWidgetItem *widget = takeItem(row);
1511  if (widget)
1512  delete widget;
1513 }
1514 
1515 void MythListBox::changeItem(const QString &new_text, uint row)
1516 {
1517  QListWidgetItem *widget = item(row);
1518  if (widget)
1519  widget->setText(new_text);
1520 }
1521 
1522 int MythListBox::getIndex(const QList<QListWidgetItem*> &list)
1523 {
1524  return (list.empty()) ? -1 : row(list[0]);
1525 }
1526 
1527 QString MythListBox::text(uint row) const
1528 {
1529  QListWidgetItem *widget = item(row);
1530  return (widget) ? widget->text() : QString::null;
1531 }
1532 
1534 {
1535  QListWidgetItem *widget = item(row);
1536  return (widget) ? !isItemHidden(widget) : false;
1537 }
1538 
1539 /* vim: set expandtab tabstop=4 shiftwidth=4: */