00001 #include <iostream>
00002 using namespace std;
00003
00004 #include <QStyle>
00005 #include <QPainter>
00006 #include <QCursor>
00007 #include <QLayout>
00008 #include <QKeyEvent>
00009 #include <QHideEvent>
00010 #include <QFocusEvent>
00011 #include <QMouseEvent>
00012 #include <QEvent>
00013
00014 #include "mythwidgets.h"
00015 #include "mythcontext.h"
00016 #include "mythmiscutil.h"
00017 #include "mythdialogs.h"
00018 #include "mythlogging.h"
00019 #include "mythmainwindow.h"
00020
00021 typedef VirtualKeyboardQt* QWidgetP;
00022 static void qt_delete(QWidgetP &widget)
00023 {
00024 if (widget)
00025 {
00026 widget->disconnect();
00027 widget->hide();
00028 widget->deleteLater();
00029 widget = NULL;
00030 }
00031 }
00032
00033 MythComboBox::MythComboBox(bool rw, QWidget *parent, const char *name) :
00034 QComboBox(parent),
00035 popup(NULL), helptext(QString::null), AcceptOnSelect(false),
00036 useVirtualKeyboard(true), allowVirtualKeyboard(rw),
00037 popupPosition(VKQT_POSBELOWEDIT), step(1)
00038 {
00039 setObjectName(name);
00040 setEditable(rw);
00041 useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
00042 }
00043
00044 MythComboBox::~MythComboBox()
00045 {
00046 Teardown();
00047 }
00048
00049 void MythComboBox::deleteLater(void)
00050 {
00051 Teardown();
00052 QComboBox::deleteLater();
00053 }
00054
00055 void MythComboBox::Teardown(void)
00056 {
00057 qt_delete(popup);
00058 }
00059
00060 void MythComboBox::setHelpText(const QString &help)
00061 {
00062 bool changed = helptext != help;
00063 helptext = help;
00064 if (hasFocus() && changed)
00065 emit changeHelpText(help);
00066 }
00067
00068 void MythComboBox::popupVirtualKeyboard(void)
00069 {
00070 qt_delete(popup);
00071
00072 popup = new VirtualKeyboardQt(GetMythMainWindow(), this);
00073 GetMythMainWindow()->detach(popup);
00074 popup->exec();
00075
00076 qt_delete(popup);
00077 }
00078
00079
00080 void MythComboBox::keyPressEvent(QKeyEvent *e)
00081 {
00082 bool handled = false, updated = false;
00083 QStringList actions;
00084 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions,
00085 !allowVirtualKeyboard);
00086
00087 if ((!popup || popup->isHidden()) && !handled)
00088 {
00089 for (int i = 0; i < actions.size() && !handled; i++)
00090 {
00091 QString action = actions[i];
00092 handled = true;
00093
00094 if (action == "UP")
00095 {
00096 focusNextPrevChild(false);
00097 }
00098 else if (action == "DOWN")
00099 {
00100 focusNextPrevChild(true);
00101 }
00102 else if (action == "LEFT")
00103 {
00104 if (currentIndex() == 0)
00105 setCurrentIndex(count()-1);
00106 else if (count() > 0)
00107 setCurrentIndex((currentIndex() - 1) % count());
00108 updated = true;
00109 }
00110 else if (action == "RIGHT")
00111 {
00112 if (count() > 0)
00113 setCurrentIndex((currentIndex() + 1) % count());
00114 updated = true;
00115 }
00116 else if (action == "PAGEDOWN")
00117 {
00118 if (currentIndex() == 0)
00119 setCurrentIndex(count() - (step % count()));
00120 else if (count() > 0)
00121 setCurrentIndex(
00122 (currentIndex() + count() - (step % count())) % count());
00123 updated = true;
00124 }
00125 else if (action == "PAGEUP")
00126 {
00127 if (count() > 0)
00128 setCurrentIndex(
00129 (currentIndex() + (step % count())) % count());
00130 updated = true;
00131 }
00132 else if (action == "SELECT" && AcceptOnSelect)
00133 emit accepted(currentIndex());
00134 else if (action == "SELECT" &&
00135 (e->text().isEmpty() ||
00136 (e->key() == Qt::Key_Enter) ||
00137 (e->key() == Qt::Key_Return) ||
00138 (e->key() == Qt::Key_Space)))
00139 {
00140 if (useVirtualKeyboard && allowVirtualKeyboard)
00141 popupVirtualKeyboard();
00142 else
00143 handled = true;
00144 }
00145
00146 else
00147 handled = false;
00148 }
00149 }
00150
00151 if (updated)
00152 {
00153 emit activated(currentIndex());
00154 emit activated(itemText(currentIndex()));
00155 }
00156 if (!handled)
00157 {
00158 if (isEditable())
00159 QComboBox::keyPressEvent(e);
00160 else
00161 e->ignore();
00162 }
00163 }
00164
00165 void MythComboBox::focusInEvent(QFocusEvent *e)
00166 {
00167 emit changeHelpText(helptext);
00168 emit gotFocus();
00169
00170 QColor highlight = palette().color(QPalette::Highlight);
00171
00172 QPalette palette;
00173 palette.setColor(backgroundRole(), highlight);
00174 setPalette(palette);
00175
00176 if (lineEdit())
00177 lineEdit()->setPalette(palette);
00178
00179 QComboBox::focusInEvent(e);
00180 }
00181
00182 void MythComboBox::focusOutEvent(QFocusEvent *e)
00183 {
00184 setPalette(QPalette());
00185
00186 if (lineEdit())
00187 {
00188 lineEdit()->setPalette(QPalette());
00189
00190
00191 QString curText = currentText();
00192 int i;
00193 bool foundItem = false;
00194
00195 for(i = 0; i < count(); i++)
00196 if (curText == itemText(i))
00197 foundItem = true;
00198
00199 if (!foundItem)
00200 {
00201 insertItem(curText);
00202 setCurrentIndex(count()-1);
00203 }
00204 }
00205
00206 QComboBox::focusOutEvent(e);
00207 }
00208
00209 void MythCheckBox::keyPressEvent(QKeyEvent* e)
00210 {
00211 bool handled = false;
00212 QStringList actions;
00213
00214 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
00215
00216 for ( int i = 0; i < actions.size() && !handled; i++)
00217 {
00218 QString action = actions[i];
00219 handled = true;
00220
00221 if (action == "UP")
00222 focusNextPrevChild(false);
00223 else if (action == "DOWN")
00224 focusNextPrevChild(true);
00225 else if (action == "LEFT" || action == "RIGHT" || action == "SELECT")
00226 toggle();
00227 else
00228 handled = false;
00229 }
00230
00231 if (!handled)
00232 e->ignore();
00233 }
00234
00235 void MythCheckBox::setHelpText(const QString &help)
00236 {
00237 bool changed = helptext != help;
00238 helptext = help;
00239 if (hasFocus() && changed)
00240 emit changeHelpText(help);
00241 }
00242
00243 void MythCheckBox::focusInEvent(QFocusEvent *e)
00244 {
00245 emit changeHelpText(helptext);
00246
00247 QColor highlight = palette().color(QPalette::Highlight);
00248 QPalette palette;
00249 palette.setColor(backgroundRole(), highlight);
00250 setPalette(palette);
00251
00252 QCheckBox::focusInEvent(e);
00253 }
00254
00255 void MythCheckBox::focusOutEvent(QFocusEvent *e)
00256 {
00257 setPalette(QPalette());
00258 QCheckBox::focusOutEvent(e);
00259 }
00260
00261 void MythRadioButton::keyPressEvent(QKeyEvent* e)
00262 {
00263 bool handled = false;
00264 QStringList actions;
00265 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
00266
00267 for (int i = 0; i < actions.size() && !handled; i++)
00268 {
00269 QString action = actions[i];
00270 handled = true;
00271
00272 if (action == "UP")
00273 focusNextPrevChild(false);
00274 else if (action == "DOWN")
00275 focusNextPrevChild(true);
00276 else if (action == "LEFT" || action == "RIGHT")
00277 toggle();
00278 else
00279 handled = false;
00280 }
00281
00282 if (!handled)
00283 e->ignore();
00284 }
00285
00286 void MythRadioButton::setHelpText(const QString &help)
00287 {
00288 bool changed = helptext != help;
00289 helptext = help;
00290 if (hasFocus() && changed)
00291 emit changeHelpText(help);
00292 }
00293
00294 void MythRadioButton::focusInEvent(QFocusEvent *e)
00295 {
00296 emit changeHelpText(helptext);
00297
00298 QColor highlight = palette().color(QPalette::Highlight);
00299
00300 QPalette palette;
00301 palette.setColor(backgroundRole(), highlight);
00302 setPalette(palette);
00303
00304 QRadioButton::focusInEvent(e);
00305 }
00306
00307 void MythRadioButton::focusOutEvent(QFocusEvent *e)
00308 {
00309 setPalette(QPalette());
00310 QRadioButton::focusOutEvent(e);
00311 }
00312
00313
00314 void MythSpinBox::setHelpText(const QString &help)
00315 {
00316 bool changed = helptext != help;
00317 helptext = help;
00318 if (hasFocus() && changed)
00319 emit changeHelpText(help);
00320 }
00321
00322 void MythSpinBox::keyPressEvent(QKeyEvent* e)
00323 {
00324 bool handled = false;
00325 QStringList actions;
00326 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
00327
00328 for (int i = 0; i < actions.size() && !handled; i++)
00329 {
00330 QString action = actions[i];
00331 handled = true;
00332
00333 if (action == "UP")
00334 focusNextPrevChild(false);
00335 else if (action == "DOWN")
00336 focusNextPrevChild(true);
00337 else if (action == "LEFT")
00338 allowsinglestep ? setValue(value()-1) : stepDown();
00339 else if (action == "RIGHT")
00340 allowsinglestep ? setValue(value()+1) : stepUp();
00341 else if (action == "PAGEDOWN")
00342 stepDown();
00343 else if (action == "PAGEUP")
00344 stepUp();
00345 else if (action == "SELECT")
00346 handled = true;
00347 else
00348 handled = false;
00349 }
00350
00351 if (!handled)
00352 QSpinBox::keyPressEvent(e);
00353 }
00354
00355 void MythSpinBox::focusInEvent(QFocusEvent *e)
00356 {
00357 emit changeHelpText(helptext);
00358
00359 QColor highlight = palette().color(QPalette::Highlight);
00360
00361 QPalette palette;
00362 palette.setColor(backgroundRole(), highlight);
00363 setPalette(palette);
00364
00365 QSpinBox::focusInEvent(e);
00366 }
00367
00368 void MythSpinBox::focusOutEvent(QFocusEvent *e)
00369 {
00370 setPalette(QPalette());
00371 QSpinBox::focusOutEvent(e);
00372 }
00373
00374 void MythSlider::keyPressEvent(QKeyEvent* e)
00375 {
00376 bool handled = false;
00377 QStringList actions;
00378 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
00379
00380 for (int i = 0; i < actions.size() && !handled; i++)
00381 {
00382 QString action = actions[i];
00383 handled = true;
00384
00385 if (action == "UP")
00386 focusNextPrevChild(false);
00387 else if (action == "DOWN")
00388 focusNextPrevChild(true);
00389 else if (action == "LEFT")
00390 setValue(value() - singleStep());
00391 else if (action == "RIGHT")
00392 setValue(value() + singleStep());
00393 else if (action == "SELECT")
00394 handled = true;
00395 else
00396 handled = false;
00397 }
00398
00399 if (!handled)
00400 QSlider::keyPressEvent(e);
00401 }
00402
00403 void MythSlider::setHelpText(const QString &help)
00404 {
00405 bool changed = helptext != help;
00406 helptext = help;
00407 if (hasFocus() && changed)
00408 emit changeHelpText(help);
00409 }
00410
00411 void MythSlider::focusInEvent(QFocusEvent *e)
00412 {
00413 emit changeHelpText(helptext);
00414
00415 QColor highlight = palette().color(QPalette::Highlight);
00416
00417 QPalette palette;
00418 palette.setColor(backgroundRole(), highlight);
00419 setPalette(palette);
00420
00421 QSlider::focusInEvent(e);
00422 }
00423
00424 void MythSlider::focusOutEvent(QFocusEvent *e)
00425 {
00426 setPalette(QPalette());
00427 QSlider::focusOutEvent(e);
00428 }
00429
00430 MythLineEdit::MythLineEdit(QWidget *parent, const char *name) :
00431 QLineEdit(parent),
00432 popup(NULL), helptext(QString::null), rw(true),
00433 useVirtualKeyboard(true),
00434 allowVirtualKeyboard(true),
00435 popupPosition(VKQT_POSBELOWEDIT)
00436 {
00437 setObjectName(name);
00438 useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
00439 }
00440
00441 MythLineEdit::MythLineEdit(
00442 const QString &contents, QWidget *parent, const char *name) :
00443 QLineEdit(contents, parent),
00444 popup(NULL), helptext(QString::null), rw(true),
00445 useVirtualKeyboard(true),
00446 allowVirtualKeyboard(true),
00447 popupPosition(VKQT_POSBELOWEDIT)
00448 {
00449 setObjectName(name);
00450 useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
00451 }
00452
00453 MythLineEdit::~MythLineEdit()
00454 {
00455 Teardown();
00456 }
00457
00458 void MythLineEdit::deleteLater(void)
00459 {
00460 Teardown();
00461 QLineEdit::deleteLater();
00462 }
00463
00464 void MythLineEdit::Teardown(void)
00465 {
00466 qt_delete(popup);
00467 }
00468
00469 void MythLineEdit::popupVirtualKeyboard(void)
00470 {
00471 qt_delete(popup);
00472
00473 popup = new VirtualKeyboardQt(GetMythMainWindow(), this);
00474 GetMythMainWindow()->detach(popup);
00475 popup->exec();
00476
00477 qt_delete(popup);
00478 }
00479
00480 void MythLineEdit::keyPressEvent(QKeyEvent *e)
00481 {
00482 bool handled = false;
00483 QStringList actions;
00484 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions, false);
00485
00486 if ((!popup || popup->isHidden()) && !handled)
00487 {
00488 for (int i = 0; i < actions.size() && !handled; i++)
00489 {
00490 QString action = actions[i];
00491 handled = true;
00492
00493 if (action == "UP")
00494 focusNextPrevChild(false);
00495 else if (action == "DOWN")
00496 focusNextPrevChild(true);
00497 else if (action == "SELECT" &&
00498 (e->text().isEmpty() ||
00499 (e->key() == Qt::Key_Enter) ||
00500 (e->key() == Qt::Key_Return)))
00501 {
00502 if (useVirtualKeyboard && allowVirtualKeyboard && rw)
00503 popupVirtualKeyboard();
00504 else
00505 handled = false;
00506 }
00507 else if (action == "SELECT" && e->text().isEmpty() )
00508 e->ignore();
00509 else
00510 handled = false;
00511 }
00512 }
00513
00514 if (!handled)
00515 if (rw || e->key() == Qt::Key_Escape || e->key() == Qt::Key_Left
00516 || e->key() == Qt::Key_Return || e->key() == Qt::Key_Right)
00517 QLineEdit::keyPressEvent(e);
00518 }
00519
00520 void MythLineEdit::setText(const QString &text)
00521 {
00522
00523
00524
00525
00526 int pos = cursorPosition();
00527 QLineEdit::setText(text);
00528 setCursorPosition(pos);
00529 }
00530
00531 QString MythLineEdit::text(void)
00532 {
00533 return QLineEdit::text();
00534 }
00535
00536 void MythLineEdit::setHelpText(const QString &help)
00537 {
00538 bool changed = helptext != help;
00539 helptext = help;
00540 if (hasFocus() && changed)
00541 emit changeHelpText(help);
00542 }
00543
00544 void MythLineEdit::focusInEvent(QFocusEvent *e)
00545 {
00546 emit changeHelpText(helptext);
00547
00548 QColor highlight = palette().color(QPalette::Highlight);
00549
00550 QPalette palette;
00551 palette.setColor(backgroundRole(), highlight);
00552 setPalette(palette);
00553
00554 QLineEdit::focusInEvent(e);
00555 }
00556
00557 void MythLineEdit::focusOutEvent(QFocusEvent *e)
00558 {
00559 setPalette(QPalette());
00560 if (popup && !popup->isHidden() && !popup->hasFocus())
00561 popup->hide();
00562 QLineEdit::focusOutEvent(e);
00563 }
00564
00565 void MythLineEdit::hideEvent(QHideEvent *e)
00566 {
00567 if (popup && !popup->isHidden())
00568 popup->hide();
00569 QLineEdit::hideEvent(e);
00570 }
00571
00572 void MythLineEdit::mouseDoubleClickEvent(QMouseEvent *e)
00573 {
00574 QLineEdit::mouseDoubleClickEvent(e);
00575 }
00576
00577 MythRemoteLineEdit::MythRemoteLineEdit(QWidget * parent, const char *name) :
00578 QTextEdit(parent)
00579 {
00580 setObjectName(name);
00581 my_font = NULL;
00582 m_lines = 1;
00583 this->Init();
00584 }
00585
00586 MythRemoteLineEdit::MythRemoteLineEdit(const QString & contents,
00587 QWidget * parent, const char *name) :
00588 QTextEdit(parent)
00589 {
00590 setObjectName(name);
00591 my_font = NULL;
00592 m_lines = 1;
00593 this->Init();
00594 setText(contents);
00595 }
00596
00597 MythRemoteLineEdit::MythRemoteLineEdit(QFont *a_font, QWidget * parent,
00598 const char *name) :
00599 QTextEdit(parent)
00600 {
00601 setObjectName(name);
00602 my_font = a_font;
00603 m_lines = 1;
00604 this->Init();
00605 }
00606
00607 MythRemoteLineEdit::MythRemoteLineEdit(int lines, QWidget * parent,
00608 const char *name) :
00609 QTextEdit(parent)
00610 {
00611 setObjectName(name);
00612 my_font = NULL;
00613 m_lines = lines;
00614 this->Init();
00615 }
00616
00617 void MythRemoteLineEdit::Init()
00618 {
00619
00620 cycle_timer = new QTimer();
00621 shift = false;
00622 active_cycle = false;
00623 current_choice = "";
00624 current_set = "";
00625
00626 cycle_time = 3000;
00627
00628 pre_cycle_text_before_cursor = "";
00629 pre_cycle_text_after_cursor = "";
00630
00631 setCharacterColors(
00632 QColor(100, 100, 100), QColor(0, 255, 255), QColor(255, 0, 0));
00633
00634
00635 setWordWrapMode(QTextOption::NoWrap);
00636
00637 if (my_font)
00638 setFont(*my_font);
00639
00640 QFontMetrics fontsize(font());
00641
00642 setMinimumHeight(fontsize.height() * 5 / 4);
00643 setMaximumHeight(fontsize.height() * m_lines * 5 / 4);
00644
00645 connect(cycle_timer, SIGNAL(timeout()), this, SLOT(endCycle()));
00646
00647 popup = NULL;
00648 useVirtualKeyboard = gCoreContext->GetNumSetting("UseVirtualKeyboard", 1);
00649 popupPosition = VKQT_POSBELOWEDIT;
00650 }
00651
00652
00653 void MythRemoteLineEdit::setCharacterColors(
00654 QColor unselected, QColor selected, QColor special)
00655 {
00656 col_unselected = unselected;
00657 hex_unselected = QString("%1%2%3")
00658 .arg(col_unselected.red(), 2, 16, QLatin1Char('0'))
00659 .arg(col_unselected.green(), 2, 16, QLatin1Char('0'))
00660 .arg(col_unselected.blue(), 2, 16, QLatin1Char('0'));
00661
00662 col_selected = selected;
00663 hex_selected = QString("%1%2%3")
00664 .arg(col_selected.red(), 2, 16, QLatin1Char('0'))
00665 .arg(col_selected.green(), 2, 16, QLatin1Char('0'))
00666 .arg(col_selected.blue(), 2, 16, QLatin1Char('0'));
00667
00668 col_special = special;
00669 hex_special = QString("%1%2%3")
00670 .arg(col_special.red(), 2, 16, QLatin1Char('0'))
00671 .arg(col_special.green(), 2, 16, QLatin1Char('0'))
00672 .arg(col_special.blue(), 2, 16, QLatin1Char('0'));
00673 }
00674
00675 void MythRemoteLineEdit::startCycle(QString current_choice, QString set)
00676 {
00677 if (active_cycle)
00678 {
00679 LOG(VB_GENERAL, LOG_ALERT,
00680 "startCycle() called, but edit is already in a cycle.");
00681 return;
00682 }
00683
00684 cycle_timer->setSingleShot(true);
00685 cycle_timer->start(cycle_time);
00686 active_cycle = true;
00687
00688 QTextCursor pre_cycle_cursor = textCursor();
00689
00690 QTextCursor upto_cursor_sel = pre_cycle_cursor;
00691 upto_cursor_sel.movePosition(
00692 QTextCursor::NoMove, QTextCursor::MoveAnchor);
00693 upto_cursor_sel.movePosition(
00694 QTextCursor::Start, QTextCursor::KeepAnchor);
00695 pre_cycle_text_before_cursor = upto_cursor_sel.selectedText();
00696
00697 QTextCursor from_cursor_sel = pre_cycle_cursor;
00698 from_cursor_sel.movePosition(
00699 QTextCursor::NoMove, QTextCursor::MoveAnchor);
00700 from_cursor_sel.movePosition(
00701 QTextCursor::End, QTextCursor::KeepAnchor);
00702 pre_cycle_text_after_cursor = from_cursor_sel.selectedText();
00703
00704 pre_cycle_pos = pre_cycle_text_before_cursor.length();
00705
00706 updateCycle(current_choice, set);
00707 }
00708
00709 void MythRemoteLineEdit::updateCycle(QString current_choice, QString set)
00710 {
00711 int index;
00712 QString aString, bString;
00713
00714
00715
00716
00717
00718
00719
00720 if (shift)
00721 {
00722 set = set.toUpper();
00723 current_choice = current_choice.toUpper();
00724 }
00725
00726 bString = "<B>";
00727 if (current_choice == "_" || current_choice == "X")
00728 {
00729 bString += "<FONT COLOR=\"#";
00730 bString += hex_special;
00731 bString += "\">";
00732 bString += current_choice;
00733 bString += "</FONT>";
00734 }
00735 else
00736 {
00737 bString += "<FONT COLOR=\"#";
00738 bString += hex_selected;
00739 bString += "\">";
00740 bString += current_choice;
00741 bString += "</FONT>";
00742 }
00743 bString += "</B>";
00744
00745 index = set.indexOf(current_choice);
00746 int length = set.length();
00747 if (index < 0 || index > length)
00748 {
00749 LOG(VB_GENERAL, LOG_ALERT,
00750 QString("MythRemoteLineEdit passed a choice of \"%1"
00751 "\" which is not in set \"%2\"")
00752 .arg(current_choice).arg(set));
00753 setText("????");
00754 return;
00755 }
00756 else
00757 {
00758 set.replace(index, current_choice.length(), bString);
00759 }
00760
00761 QString esc_upto = pre_cycle_text_before_cursor;
00762 QString esc_from = pre_cycle_text_after_cursor;
00763
00764 esc_upto.replace("<", "<").replace(">", ">").replace("\n", "<br>");
00765 esc_from.replace("<", "<").replace(">", ">").replace("\n", "<br>");
00766
00767 aString = esc_upto;
00768 aString += "<FONT COLOR=\"#";
00769 aString += hex_unselected;
00770 aString += "\">[";
00771 aString += set;
00772 aString += "]</FONT>";
00773 aString += esc_from;
00774 setHtml(aString);
00775
00776 QTextCursor tmp = textCursor();
00777 tmp.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
00778 tmp.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor,
00779 pre_cycle_pos + set.length());
00780 setTextCursor(tmp);
00781 update();
00782
00783 if (current_choice == "X" && !pre_cycle_text_before_cursor.isEmpty())
00784 {
00785
00786 QTextCursor tmp = textCursor();
00787 tmp.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
00788 tmp.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor,
00789 pre_cycle_pos - 1);
00790 tmp.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
00791 setTextCursor(tmp);
00792 }
00793 else
00794 {
00795
00796 QTextCursor tmp = textCursor();
00797 tmp.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
00798 tmp.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor,
00799 pre_cycle_pos);
00800 setTextCursor(tmp);
00801 }
00802 }
00803
00804 void MythRemoteLineEdit::endCycle(bool select)
00805 {
00806 if (!active_cycle)
00807 return;
00808
00809 QString tmpString = "";
00810 int pos = pre_cycle_pos;
00811
00812
00813
00814 if (!select)
00815 {
00816 tmpString = pre_cycle_text_before_cursor;
00817 }
00818 else if (current_choice == "X")
00819 {
00820 if (!pre_cycle_text_before_cursor.isEmpty())
00821 {
00822 tmpString = pre_cycle_text_before_cursor.left(
00823 pre_cycle_text_before_cursor.length() - 1);
00824 pos--;
00825 }
00826 }
00827 else
00828 {
00829 current_choice = (current_choice == "_") ? " " : current_choice;
00830 current_choice = (shift) ? current_choice.toUpper() : current_choice;
00831
00832 tmpString = pre_cycle_text_before_cursor;
00833 tmpString += current_choice;
00834 pos++;
00835 }
00836
00837 tmpString += pre_cycle_text_after_cursor;
00838
00839 setPlainText(tmpString);
00840
00841 QTextCursor tmpCursor = textCursor();
00842 tmpCursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
00843 tmpCursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, pos);
00844 setTextCursor(tmpCursor);
00845
00846 active_cycle = false;
00847 current_choice = "";
00848 current_set = "";
00849 pre_cycle_text_before_cursor = "";
00850 pre_cycle_text_after_cursor = "";
00851
00852 if (select)
00853 emit textChanged(toPlainText());
00854 }
00855
00856 void MythRemoteLineEdit::setText(const QString &text)
00857 {
00858 QTextEdit::clear();
00859 QTextEdit::insertPlainText(text);
00860 }
00861
00862 QString MythRemoteLineEdit::text(void)
00863 {
00864 return QTextEdit::toPlainText();
00865 }
00866
00867 void MythRemoteLineEdit::keyPressEvent(QKeyEvent *e)
00868 {
00869 bool handled = false;
00870 QStringList actions;
00871 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions, false);
00872
00873 if ((!popup || popup->isHidden()) && !handled)
00874 {
00875 for (int i = 0; i < actions.size() && !handled; i++)
00876 {
00877 QString action = actions[i];
00878 handled = true;
00879
00880 if (action == "UP")
00881 {
00882 endCycle();
00883
00884
00885
00886
00887 QWidget::focusNextPrevChild(false);
00888 emit tryingToLooseFocus(false);
00889 }
00890 else if (action == "DOWN")
00891 {
00892 endCycle();
00893 QWidget::focusNextPrevChild(true);
00894 emit tryingToLooseFocus(true);
00895 }
00896 else if ((action == "SELECT") &&
00897 (!active_cycle) &&
00898 ((e->text().isEmpty()) ||
00899 (e->key() == Qt::Key_Enter) ||
00900 (e->key() == Qt::Key_Return)))
00901 {
00902 if (useVirtualKeyboard)
00903 popupVirtualKeyboard();
00904 }
00905 else if ((action == "ESCAPE") && active_cycle)
00906 {
00907 endCycle(false);
00908 }
00909 else
00910 handled = false;
00911 }
00912 }
00913
00914 if (handled)
00915 return;
00916
00917 if (popup && !popup->isHidden())
00918 {
00919 endCycle();
00920 QTextEdit::keyPressEvent(e);
00921 emit textChanged(toPlainText());
00922 return;
00923 }
00924
00925 switch (e->key())
00926 {
00927 case Qt::Key_Enter:
00928 case Qt::Key_Return:
00929 handled = true;
00930 endCycle();
00931 e->ignore();
00932 break;
00933
00934
00935
00936 case Qt::Key_Space:
00937 if (active_cycle)
00938 {
00939 handled = true;
00940 endCycle();
00941 e->ignore();
00942 }
00943 break;
00944
00945
00946
00947
00948 case Qt::Key_1:
00949 cycleKeys("_X%-/.?()1");
00950 handled = true;
00951 break;
00952
00953 case Qt::Key_2:
00954 cycleKeys("abc2");
00955 handled = true;
00956 break;
00957
00958 case Qt::Key_3:
00959 cycleKeys("def3");
00960 handled = true;
00961 break;
00962
00963 case Qt::Key_4:
00964 cycleKeys("ghi4");
00965 handled = true;
00966 break;
00967
00968 case Qt::Key_5:
00969 cycleKeys("jkl5");
00970 handled = true;
00971 break;
00972
00973 case Qt::Key_6:
00974 cycleKeys("mno6");
00975 handled = true;
00976 break;
00977
00978 case Qt::Key_7:
00979 cycleKeys("pqrs7");
00980 handled = true;
00981 break;
00982
00983 case Qt::Key_8:
00984 cycleKeys("tuv8");
00985 handled = true;
00986 break;
00987
00988 case Qt::Key_9:
00989 cycleKeys("wxyz90");
00990 handled = true;
00991 break;
00992
00993 case Qt::Key_0:
00994 toggleShift();
00995 handled = true;
00996 break;
00997 }
00998
00999 if (!handled)
01000 {
01001 endCycle();
01002 QTextEdit::keyPressEvent(e);
01003 emit textChanged(toPlainText());
01004 }
01005 }
01006
01007 void MythRemoteLineEdit::setCycleTime(float desired_interval)
01008 {
01009 if (desired_interval < 0.5 || desired_interval > 10.0)
01010 {
01011 LOG(VB_GENERAL, LOG_ALERT,
01012 QString("cycle interval of %1 milliseconds ")
01013 .arg((int) (desired_interval * 1000)) +
01014 "\n\t\t\tis outside of the allowed range of "
01015 "500 to 10,000 milliseconds");
01016 return;
01017 }
01018
01019 cycle_time = (int) (desired_interval * 1000);
01020 }
01021
01022 void MythRemoteLineEdit::cycleKeys(QString cycle_list)
01023 {
01024 int index;
01025
01026 if (active_cycle)
01027 {
01028 if (cycle_list == current_set)
01029 {
01030
01031 cycle_timer->start(cycle_time);
01032 index = current_set.indexOf(current_choice);
01033 int length = current_set.length();
01034 if (index + 1 >= length)
01035 {
01036 index = -1;
01037 }
01038 current_choice = current_set.mid(index + 1, 1);
01039 updateCycle(current_choice, current_set);
01040 }
01041 else
01042 {
01043
01044
01045 endCycle();
01046 current_choice = cycle_list.left(1);
01047 current_set = cycle_list;
01048 cycle_timer->start(cycle_time);
01049 startCycle(current_choice, current_set);
01050 }
01051 }
01052 else
01053 {
01054
01055 current_choice = cycle_list.left(1);
01056 current_set = cycle_list;
01057 startCycle(current_choice, current_set);
01058 }
01059 }
01060
01061 void MythRemoteLineEdit::toggleShift()
01062 {
01063
01064
01065
01066 QString temp_choice = current_choice;
01067 QString temp_set = current_set;
01068
01069 if (shift)
01070 {
01071 shift = false;
01072 }
01073 else
01074 {
01075 shift = true;
01076 temp_choice = current_choice.toUpper();
01077 temp_set = current_set.toUpper();
01078 }
01079 if (active_cycle)
01080 {
01081 updateCycle(temp_choice, temp_set);
01082 }
01083 }
01084
01085 void MythRemoteLineEdit::setHelpText(const QString &help)
01086 {
01087 bool changed = helptext != help;
01088 helptext = help;
01089 if (hasFocus() && changed)
01090 emit changeHelpText(help);
01091 }
01092
01093 void MythRemoteLineEdit::focusInEvent(QFocusEvent *e)
01094 {
01095 emit changeHelpText(helptext);
01096 emit gotFocus();
01097
01098 QColor highlight = palette().color(QPalette::Highlight);
01099
01100 QPalette palette;
01101 palette.setColor(backgroundRole(), highlight);
01102 setPalette(palette);
01103
01104 QTextEdit::focusInEvent(e);
01105 }
01106
01107 void MythRemoteLineEdit::focusOutEvent(QFocusEvent *e)
01108 {
01109 setPalette(QPalette());
01110
01111 if (popup && !popup->isHidden() && !popup->hasFocus())
01112 popup->hide();
01113
01114 emit lostFocus();
01115 QTextEdit::focusOutEvent(e);
01116 }
01117
01118 MythRemoteLineEdit::~MythRemoteLineEdit()
01119 {
01120 Teardown();
01121 }
01122
01123 void MythRemoteLineEdit::deleteLater(void)
01124 {
01125 Teardown();
01126 QTextEdit::deleteLater();
01127 }
01128
01129 void MythRemoteLineEdit::Teardown(void)
01130 {
01131 if (cycle_timer)
01132 {
01133 cycle_timer->disconnect();
01134 cycle_timer->deleteLater();
01135 cycle_timer = NULL;
01136 }
01137
01138 qt_delete(popup);
01139 }
01140
01141 void MythRemoteLineEdit::popupVirtualKeyboard(void)
01142 {
01143 qt_delete(popup);
01144
01145 popup = new VirtualKeyboardQt(GetMythMainWindow(), this);
01146 GetMythMainWindow()->detach(popup);
01147 popup->exec();
01148
01149 qt_delete(popup);
01150 }
01151
01152 void MythRemoteLineEdit::insert(QString text)
01153 {
01154 QTextEdit::insertPlainText(text);
01155 emit textChanged(toPlainText());
01156 }
01157
01158 void MythRemoteLineEdit::del()
01159 {
01160 textCursor().deleteChar();
01161 emit textChanged(toPlainText());
01162 }
01163
01164 void MythRemoteLineEdit::backspace()
01165 {
01166 textCursor().deletePreviousChar();
01167 emit textChanged(toPlainText());
01168 }
01169
01170 MythPushButton::MythPushButton(const QString &ontext, const QString &offtext,
01171 QWidget *parent, bool isOn)
01172 : QPushButton(ontext, parent)
01173 {
01174 onText = ontext;
01175 offText = offtext;
01176
01177 setCheckable(true);
01178
01179 if (isOn)
01180 setText(onText);
01181 else
01182 setText(offText);
01183
01184 setChecked(isOn);
01185 }
01186
01187 void MythPushButton::setHelpText(const QString &help)
01188 {
01189 bool changed = helptext != help;
01190 helptext = help;
01191 if (hasFocus() && changed)
01192 emit changeHelpText(help);
01193 }
01194
01195 void MythPushButton::keyPressEvent(QKeyEvent *e)
01196 {
01197 bool handled = false;
01198 QStringList actions;
01199 keyPressActions.clear();
01200
01201 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
01202
01203 if (!handled && !actions.isEmpty())
01204 {
01205 keyPressActions = actions;
01206
01207 for (int i = 0; i < actions.size() && !handled; i++)
01208 {
01209 QString action = actions[i];
01210 if (action == "SELECT")
01211 {
01212 if (isCheckable())
01213 toggleText();
01214 setDown(true);
01215 emit pressed();
01216 handled = true;
01217 }
01218 }
01219 }
01220
01221 if (!handled)
01222 QPushButton::keyPressEvent(e);
01223 }
01224
01225 void MythPushButton::keyReleaseEvent(QKeyEvent *e)
01226 {
01227 bool handled = false;
01228 QStringList actions = keyPressActions;
01229 for (int i = 0; i < actions.size() && !handled; i++)
01230 {
01231 QString action = actions[i];
01232 if (action == "SELECT")
01233 {
01234 QKeyEvent tempe(QEvent::KeyRelease, Qt::Key_Space,
01235 Qt::NoModifier, " ");
01236 QPushButton::keyReleaseEvent(&tempe);
01237 handled = true;
01238 }
01239 }
01240
01241 if (!handled)
01242 QPushButton::keyReleaseEvent(e);
01243 }
01244
01245 void MythPushButton::toggleText(void)
01246 {
01247 if (!isCheckable())
01248 return;
01249
01250 if (isChecked())
01251 setText(offText);
01252 else
01253 setText(onText);
01254 }
01255
01256 void MythPushButton::focusInEvent(QFocusEvent *e)
01257 {
01258 emit changeHelpText(helptext);
01259
01260 QColor highlight = palette().color(QPalette::Highlight);
01261 QPalette palette;
01262 palette.setColor(backgroundRole(), highlight);
01263 setPalette(palette);
01264
01265 QPushButton::focusInEvent(e);
01266 }
01267
01268 void MythPushButton::focusOutEvent(QFocusEvent *e)
01269 {
01270 setPalette(QPalette());
01271 QPushButton::focusOutEvent(e);
01272 }
01273
01274 MythListBox::MythListBox(QWidget *parent, const QString &name) :
01275 QListWidget(parent)
01276 {
01277 setObjectName(name);
01278 connect(this, SIGNAL(itemSelectionChanged()),
01279 this, SLOT(HandleItemSelectionChanged()));
01280 }
01281
01282 void MythListBox::ensurePolished(void) const
01283 {
01284 QListWidget::ensurePolished();
01285
01286 QPalette pal = palette();
01287 QPalette::ColorRole nR = QPalette::Highlight;
01288 QPalette::ColorGroup oA = QPalette::Active;
01289 QPalette::ColorRole oR = QPalette::Button;
01290 pal.setColor(QPalette::Active, nR, pal.color(oA,oR));
01291 pal.setColor(QPalette::Inactive, nR, pal.color(oA,oR));
01292 pal.setColor(QPalette::Disabled, nR, pal.color(oA,oR));
01293
01294 const_cast<MythListBox*>(this)->setPalette(pal);
01295 }
01296
01297 void MythListBox::setCurrentItem(const QString& matchText, bool caseSensitive,
01298 bool partialMatch)
01299 {
01300 for (unsigned i = 0 ; i < (unsigned)count() ; ++i)
01301 {
01302 if (partialMatch)
01303 {
01304 if (caseSensitive)
01305 {
01306 if (text(i).startsWith(matchText))
01307 {
01308 setCurrentRow(i);
01309 break;
01310 }
01311 }
01312 else
01313 {
01314 if (text(i).toLower().startsWith(matchText.toLower()))
01315 {
01316 setCurrentRow(i);
01317 break;
01318 }
01319 }
01320 }
01321 else
01322 {
01323 if (caseSensitive)
01324 {
01325 if (text(i) == matchText)
01326 {
01327 setCurrentRow(i);
01328 break;
01329 }
01330 }
01331 else
01332 {
01333 if (text(i).toLower() == matchText.toLower())
01334 {
01335 setCurrentRow(i);
01336 break;
01337 }
01338 }
01339 }
01340 }
01341 }
01342
01343 void MythListBox::HandleItemSelectionChanged(void)
01344 {
01345 QList<QListWidgetItem*> items = QListWidget::selectedItems();
01346 int row = getIndex(items);
01347 if (row >= 0)
01348 emit highlighted(row);
01349 }
01350
01351 void MythListBox::keyPressEvent(QKeyEvent* e)
01352 {
01353 bool handled = false;
01354 QStringList actions;
01355 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
01356
01357 for (int i = 0; i < actions.size() && !handled; i++)
01358 {
01359 QString action = actions[i];
01360 if (action == "UP" || action == "DOWN" || action == "PAGEUP" ||
01361 action == "PAGEDOWN" || action == "LEFT" || action == "RIGHT")
01362 {
01363 int key;
01364 if (action == "UP")
01365 {
01366
01367 if (currentItem() == 0)
01368 {
01369 focusNextPrevChild(false);
01370 handled = true;
01371 continue;
01372 }
01373
01374 key = Qt::Key_Up;
01375 }
01376 else if (action == "DOWN")
01377 {
01378
01379 if (currentRow() == (int) count() - 1)
01380 {
01381 focusNextPrevChild(true);
01382 handled = true;
01383 continue;
01384 }
01385
01386 key = Qt::Key_Down;
01387 }
01388 else if (action == "LEFT")
01389 {
01390 focusNextPrevChild(false);
01391 handled = true;
01392 continue;
01393 }
01394 else if (action == "RIGHT")
01395 {
01396 focusNextPrevChild(true);
01397 handled = true;
01398 continue;
01399 }
01400 else if (action == "PAGEUP")
01401 key = Qt::Key_PageUp;
01402 else if (action == "PAGEDOWN")
01403 key = Qt::Key_PageDown;
01404 else
01405 key = Qt::Key_unknown;
01406
01407 QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier);
01408 QListWidget::keyPressEvent(&ev);
01409 handled = true;
01410 }
01411 else if (action == "0" || action == "1" || action == "2" ||
01412 action == "3" || action == "4" || action == "5" ||
01413 action == "6" || action == "7" || action == "8" ||
01414 action == "9")
01415 {
01416 int percent = action.toInt() * 10;
01417 int nextItem = percent * count() / 100;
01418 if (!itemVisible(nextItem))
01419 setTopRow(nextItem);
01420 setCurrentRow(nextItem);
01421 handled = true;
01422 }
01423 else if (action == "PREVVIEW")
01424 {
01425 int nextItem = currentRow();
01426 if (nextItem > 0)
01427 nextItem--;
01428 while (nextItem > 0 && text(nextItem)[0] == ' ')
01429 nextItem--;
01430 if (!itemVisible(nextItem))
01431 setTopRow(nextItem);
01432 setCurrentRow(nextItem);
01433 handled = true;
01434 }
01435 else if (action == "NEXTVIEW")
01436 {
01437 int nextItem = currentRow();
01438 if (nextItem < (int)count() - 1)
01439 nextItem++;
01440 while (nextItem < (int)count() - 1 && text(nextItem)[0] == ' ')
01441 nextItem++;
01442 if (!itemVisible(nextItem))
01443 setTopRow(nextItem);
01444 setCurrentRow(nextItem);
01445 handled = true;
01446 }
01447 else if (action == "MENU")
01448 emit menuButtonPressed(currentRow());
01449 else if (action == "EDIT")
01450 emit editButtonPressed(currentRow());
01451 else if (action == "DELETE")
01452 emit deleteButtonPressed(currentRow());
01453 else if (action == "SELECT")
01454 emit accepted(currentRow());
01455 }
01456
01457 if (!handled)
01458 e->ignore();
01459 }
01460
01461 void MythListBox::setHelpText(const QString &help)
01462 {
01463 bool changed = helptext != help;
01464 helptext = help;
01465 if (hasFocus() && changed)
01466 emit changeHelpText(help);
01467 }
01468
01469 void MythListBox::focusOutEvent(QFocusEvent *e)
01470 {
01471 QPalette pal = palette();
01472 QPalette::ColorRole nR = QPalette::Highlight;
01473 QPalette::ColorGroup oA = QPalette::Active;
01474 QPalette::ColorRole oR = QPalette::Button;
01475 pal.setColor(QPalette::Active, nR, pal.color(oA,oR));
01476 pal.setColor(QPalette::Inactive, nR, pal.color(oA,oR));
01477 pal.setColor(QPalette::Disabled, nR, pal.color(oA,oR));
01478 setPalette(pal);
01479 QListWidget::focusOutEvent(e);
01480 }
01481
01482 void MythListBox::focusInEvent(QFocusEvent *e)
01483 {
01484 setPalette(QPalette());
01485
01486 emit changeHelpText(helptext);
01487 QListWidget::focusInEvent(e);
01488 }
01489
01490
01491 void MythListBox::setTopRow(uint row)
01492 {
01493 QListWidgetItem *widget = item(row);
01494 if (widget)
01495 scrollToItem(widget, QAbstractItemView::PositionAtTop);
01496 }
01497
01498 void MythListBox::insertItem(const QString &label)
01499 {
01500 addItem(label);
01501 }
01502
01503 void MythListBox::insertStringList(const QStringList &label_list)
01504 {
01505 addItems(label_list);
01506 }
01507
01508 void MythListBox::removeRow(uint row)
01509 {
01510 QListWidgetItem *widget = takeItem(row);
01511 if (widget)
01512 delete widget;
01513 }
01514
01515 void MythListBox::changeItem(const QString &new_text, uint row)
01516 {
01517 QListWidgetItem *widget = item(row);
01518 if (widget)
01519 widget->setText(new_text);
01520 }
01521
01522 int MythListBox::getIndex(const QList<QListWidgetItem*> &list)
01523 {
01524 return (list.empty()) ? -1 : row(list[0]);
01525 }
01526
01527 QString MythListBox::text(uint row) const
01528 {
01529 QListWidgetItem *widget = item(row);
01530 return (widget) ? widget->text() : QString::null;
01531 }
01532
01533 bool MythListBox::itemVisible(uint row) const
01534 {
01535 QListWidgetItem *widget = item(row);
01536 return (widget) ? !isItemHidden(widget) : false;
01537 }
01538
01539