324 | | bool handled = false; |
325 | | QStringList actions; |
326 | | if (gContext->GetMainWindow()->TranslateKeyPress("qt", e, actions)) |
| 327 | setFrameStyle( WinPanel|Raised ); |
| 328 | |
| 329 | QString k[alphabuts] = { |
| 330 | "`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", |
| 331 | "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\", |
| 332 | "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", |
| 333 | "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", |
| 334 | " " |
| 335 | }; |
| 336 | |
| 337 | QString k2[alphabuts] = { |
| 338 | "~", "!", "@", "#", "$", "%", "^", "&&", "*", "(", ")", "_", "+", |
| 339 | "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "{", "}", "|", |
| 340 | "A", "S", "D", "F", "G", "H", "J", "K", "L", ":", "\"", |
| 341 | "Z", "X", "C", "V", "B", "N", "M", "<", ">", "?", |
| 342 | " " |
| 343 | }; |
| 344 | |
| 345 | static int x[alphabuts] = { |
| 346 | 5, 35, 65, 95, 125, 155, 185, 215, 245, 275, 305, 335, 365, |
| 347 | 40, 70, 100, 130, 160, 190, 220, 250, 280, 310, 340, 370, 400, |
| 348 | 45, 75, 105, 135, 165, 195, 225, 255, 285, 315, 345, |
| 349 | 50, 80, 110, 140, 170, 200, 230, 260, 290, 320, |
| 350 | 160 |
| 351 | }; |
| 352 | |
| 353 | static int y[alphabuts] = { |
| 354 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 355 | 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, |
| 356 | 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, |
| 357 | 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, |
| 358 | 125 |
| 359 | }; |
| 360 | |
| 361 | static int w[alphabuts] = { |
| 362 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, |
| 363 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, |
| 364 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, |
| 365 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, |
| 366 | 80 |
| 367 | }; |
| 368 | |
| 369 | for (int i=0; i<alphabuts; i++) |
333 | | if (action == "UP") |
334 | | focusNextPrevChild(false); |
335 | | else if (action == "DOWN") |
336 | | focusNextPrevChild(true); |
337 | | else if (action == "SELECT" && e->text().isNull()) |
338 | | e->ignore(); |
339 | | else |
340 | | handled = false; |
| 375 | but[iDone] = new VKButton(this, "Done button", "Done"); |
| 376 | but[iDone]->setGeometry(375, 65, 70, 25); |
| 377 | but[iDone]->highlight(true); // Default highlighted key. |
| 378 | |
| 379 | but[iShift] = new VKButton(this, "Shift button", "Shift"); |
| 380 | but[iShift]->setGeometry(5, 125, 60, 25); |
| 381 | but[iShift]->setToggleButton( true ); |
| 382 | but[iShift]->setOn( false ); |
| 383 | |
| 384 | but[iLock] = new VKButton(this, "Shift lock button", "Lock"); |
| 385 | but[iLock]->setGeometry(70, 125, 60, 25); |
| 386 | but[iLock]->setToggleButton( true ); |
| 387 | but[iLock]->setOn( false ); |
| 388 | |
| 389 | but[iLeft] = new VKButton(this, "Left arrow", "<-"); |
| 390 | but[iLeft]->setGeometry(270, 125, 40, 25); |
| 391 | |
| 392 | but[iRight] = new VKButton(this, "Right arrow", "->"); |
| 393 | but[iRight]->setGeometry(315, 125, 40, 25); |
| 394 | |
| 395 | but[iBack] = new VKButton(this, "Backspace", "Back"); |
| 396 | but[iBack]->setGeometry(395, 5, 50, 25); |
| 397 | |
| 398 | but[iDel] = new VKButton(this, "Delete", "Del"); |
| 399 | but[iDel]->setGeometry(350, 95, 40, 25); |
| 400 | |
| 401 | connect(but[iDone], SIGNAL( released() ), this, SLOT( closePopup() ) ); |
| 402 | connect(but[iShift], SIGNAL( released() ), this, SLOT( shiftOnOff() ) ); |
| 403 | connect(but[iLock], SIGNAL( released() ), this, SLOT( lockOnOff() ) ); |
| 404 | connect(but[iLeft], SIGNAL( released() ), parent, SLOT( lCursor() ) ); |
| 405 | connect(but[iRight], SIGNAL( released() ), parent, SLOT( rCursor() ) ); |
| 406 | connect(but[iBack], SIGNAL( released() ), parent, SLOT( backPressed() ) ); |
| 407 | connect(but[iDel], SIGNAL( released() ), parent, SLOT( delPressed() ) ); |
| 408 | } |
| 409 | |
| 410 | VKPopup::~VKPopup() |
| 411 | { |
| 412 | for (int i=0; i<(alphabuts+specialbuts); i++) |
| 413 | { |
| 414 | if (but[i]) { delete but[i]; } |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | void VKPopup::openPopup() |
| 419 | { |
| 420 | QWidget *pw = parentWidget(); |
| 421 | QWidget *tlw = pw->topLevelWidget(); |
| 422 | QRect pwg = pw->geometry(); |
| 423 | QRect tlwg = tlw->frameGeometry(); |
| 424 | |
| 425 | QPoint newpos; |
| 426 | if (pw->mapTo(tlw, QPoint(0,pwg.height()+popuph+5)).y() |
| 427 | < tlwg.height()) |
| 428 | { |
| 429 | newpos = QPoint(pwg.width()/2-popupw/2, pwg.height() + 5); |
| 430 | } |
| 431 | else { |
| 432 | newpos = QPoint(pwg.width()/2-popupw/2, -5-popuph); |
| 433 | } |
| 434 | |
| 435 | int delx = pw->mapTo(tlw,newpos).x() + popupw-tlwg.width(); |
| 436 | newpos = QPoint(newpos.x()-(delx > 0 ? delx : 0), newpos.y()); |
| 437 | delx = pw->mapTo(tlw, newpos).x(); |
| 438 | newpos = QPoint(newpos.x()-(delx < 0 ? delx : 0), newpos.y()); |
| 439 | // FIXME: should we blank the cursor? |
| 440 | this->resize(popupw,popuph); |
| 441 | this->move( pw->mapToGlobal( newpos ) ); |
| 442 | this->grabKeyboard(); |
| 443 | this->show(); |
| 444 | pw->setFocus(); |
| 445 | } |
| 446 | |
| 447 | void VKPopup::closePopup() |
| 448 | { |
| 449 | this->hide(); |
| 450 | this->releaseKeyboard(); |
| 451 | parentWidget()->setFocus(); |
| 452 | } |
| 453 | |
| 454 | void VKPopup::focusInEvent(QFocusEvent *e) |
| 455 | { |
| 456 | QFrame::focusInEvent(e); |
| 457 | parentWidget()->setFocus(); //Should not take focus from line edit |
| 458 | } |
| 459 | |
| 460 | void VKPopup::lockOnOff() |
| 461 | { |
| 462 | but[iShift]->setOn(but[iLock]->isOn()); |
| 463 | shiftOnOff(); |
| 464 | } |
| 465 | |
| 466 | void VKPopup::shiftOff() |
| 467 | { |
| 468 | if (!but[iLock]->isOn()) |
| 469 | { |
| 470 | but[iShift]->setOn(false); |
| 471 | } |
| 472 | shiftOnOff(); |
| 473 | } |
| 474 | |
| 475 | void VKPopup::shiftOnOff() |
| 476 | { |
| 477 | bool newstate = but[iShift]->isOn(); |
| 478 | for (int i=0; i<alphabuts; i++) |
| 479 | { |
| 480 | but[i]->setShiftState(newstate); |
| 481 | } |
| 482 | if (!newstate) |
| 483 | { |
| 484 | but[iLock]->setOn(false); |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | VKButton * VKPopup::sideButton(VKButton * oldbut, int dirkey) |
| 489 | { |
| 490 | QRect butrect = oldbut->frameGeometry(); |
| 491 | QPoint newpoint; |
| 492 | switch (dirkey) { |
| 493 | case Qt::Key_Left: |
| 494 | newpoint = QPoint(butrect.left()-25, butrect.center().y()); |
| 495 | break; |
| 496 | case Qt::Key_Right: |
| 497 | newpoint = QPoint(butrect.right()+25, butrect.center().y()); |
| 498 | break; |
| 499 | case Qt::Key_Up: |
| 500 | newpoint = QPoint(butrect.center().x(), butrect.top()-25); |
| 501 | break; |
| 502 | case Qt::Key_Down: |
| 503 | newpoint = QPoint(butrect.center().x(), butrect.bottom()+25); |
| 504 | break; |
| 505 | } |
| 506 | int ibest = 0; |
| 507 | int bestdist = (newpoint - but[ibest]->frameGeometry().center()).manhattanLength(); |
| 508 | for (int i=0; i<(alphabuts+specialbuts); i++) |
| 509 | { |
| 510 | int thisdist = (newpoint - but[i]->frameGeometry().center()).manhattanLength(); |
| 511 | if (thisdist < bestdist) { |
| 512 | bestdist = thisdist; |
| 513 | ibest = i; |
| 557 | |
| 558 | VKButton::VKButton(QWidget *parent, const char* name, const char* text, |
| 559 | const char* textSh, QLineEdit *ebox): |
| 560 | QPushButton(text, parent, name) |
| 561 | { |
| 562 | mykey1 = text; |
| 563 | mykey2 = textSh; |
| 564 | mybox = ebox; |
| 565 | setText(mykey1); |
| 566 | setShiftState(false); |
| 567 | highlight(false); |
| 568 | if (mybox) |
| 569 | { |
| 570 | // Regular keys pass their own text and tell the shift button |
| 571 | // they've been pressed. |
| 572 | connect (this, SIGNAL( pressed() ), SLOT ( pressKey() ) ); |
| 573 | connect (this, SIGNAL( released() ), parent, SLOT( shiftOff() ) ); |
| 574 | } |
| 575 | } |
| 576 | |
| 577 | void VKButton::highlight(bool b) |
| 578 | { |
| 579 | setFlat(!b); |
| 580 | setDefault(b); |
| 581 | } |
| 582 | |
| 583 | bool VKButton::isHighlighted() |
| 584 | { |
| 585 | return (!isFlat()); |
| 586 | } |
| 587 | |
| 588 | void VKButton::setShiftState(bool state) |
| 589 | { |
| 590 | if (state) { setText(mykey2); } |
| 591 | else { setText(mykey1); } |
| 592 | } |
| 593 | |
| 594 | void VKButton::pressKey() |
| 595 | { |
| 596 | if (text().mid(0,1) == "&") |
| 597 | { |
| 598 | mybox->insert(text().mid(1,1)); |
| 599 | } |
| 600 | else |
| 601 | { |
| 602 | mybox->insert(text().mid(0,1)); |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | void MythLineEdit::Init() |
| 607 | { |
| 608 | usevk = (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1); |
| 609 | if (usevk) |
| 610 | { |
| 611 | popup = new VKPopup(this, "Popup Virtual Keyboard"); |
| 612 | connect(this, SIGNAL( returnPressed() ), popup, SLOT(openPopup())); |
| 613 | } |
| 614 | } |
| 615 | |
| 616 | void MythLineEdit::keyPressEvent(QKeyEvent *e) |
| 617 | { |
| 618 | if (usevk && popup->isShown()) |
| 619 | { |
| 620 | // So that popup gets keys even though not in focus. |
| 621 | QApplication::sendEvent(popup, e); |
| 622 | setFocus(); |
| 623 | } |
| 624 | else |
| 625 | { |
| 626 | bool handled = false; |
| 627 | QStringList actions; |
| 628 | if (gContext->GetMainWindow()->TranslateKeyPress("qt", e, actions)) |
| 629 | { |
| 630 | for (unsigned int i = 0; i < actions.size() && !handled; i++) |
| 631 | { |
| 632 | QString action = actions[i]; |
| 633 | handled = true; |
| 634 | |
| 635 | if (action == "UP") |
| 636 | focusNextPrevChild(false); |
| 637 | else if (action == "DOWN") |
| 638 | focusNextPrevChild(true); |
| 639 | else if (usevk && popup |
| 640 | && (action == "SELECT") && e->text().isNull()) |
| 641 | popup->openPopup(); |
| 642 | else |
| 643 | handled = false; |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | if (!handled) |
| 648 | if (rw || e->key() == Key_Escape) |
| 649 | QLineEdit::keyPressEvent(e); |
| 650 | } |
| 651 | } |
| 652 | |