Ticket #27: mythtv_svn_virtual_keyboard.svn.diff

File mythtv_svn_virtual_keyboard.svn.diff, 14.3 KB (added by jkondis <jkondis@…>, 16 years ago)

Patch introduces virtual keyboard function to myth line edits.

  • libs/libmyth/mythwidgets.cpp

     
    319319    QSlider::focusOutEvent(e);
    320320}
    321321
    322 void MythLineEdit::keyPressEvent(QKeyEvent *e)
     322// Some Virtual Keyboard-related stuff
     323
     324VKPopup::VKPopup(QWidget *parent, const char* name)
     325    : QFrame(parent, name, WType_Popup)
    323326{
    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++)
    327370    {
    328         for (unsigned int i = 0; i < actions.size() && !handled; i++)
    329         {
    330             QString action = actions[i];
    331             handled = true;
     371        but[i] = new VKButton(this, k[i], k[i], k2[i], (QLineEdit *)parent);
     372        but[i]->setGeometry(x[i], y[i], w[i], 25);
     373    }
    332374
    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
     410VKPopup::~VKPopup()
     411{
     412    for (int i=0; i<(alphabuts+specialbuts); i++)
     413    {
     414        if (but[i]) { delete but[i]; }
     415    }
     416}
     417
     418void 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
     447void VKPopup::closePopup()
     448{
     449    this->hide();
     450    this->releaseKeyboard();
     451    parentWidget()->setFocus();
     452}
     453
     454void VKPopup::focusInEvent(QFocusEvent *e)
     455{
     456    QFrame::focusInEvent(e);
     457    parentWidget()->setFocus();   //Should not take focus from line edit
     458}
     459
     460void VKPopup::lockOnOff()
     461{
     462    but[iShift]->setOn(but[iLock]->isOn());
     463    shiftOnOff();
     464}
     465
     466void VKPopup::shiftOff()
     467{
     468    if (!but[iLock]->isOn())
     469    {
     470        but[iShift]->setOn(false);
     471    }
     472    shiftOnOff();
     473}
     474
     475void 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
     488VKButton * 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;
    341514        }
    342515    }
     516    return but[ibest];
     517}
    343518
    344     if (!handled)
    345         if (rw || e->key() == Key_Escape)
    346             QLineEdit::keyPressEvent(e);
     519void VKPopup::keyPressEvent(QKeyEvent *e)
     520{
     521    if (e->type() == QEvent::KeyPress) {
     522        int selected = 0;
     523        for (int i=0; i<(alphabuts+specialbuts); i++)
     524        {
     525            if (but[i]->isHighlighted())
     526            {
     527                selected = i;
     528                break;
     529            }
     530        }
     531        switch (e->key())
     532        {
     533            case Qt::Key_Escape:
     534                closePopup();
     535                e->accept();
     536                break;
     537            case Qt::Key_Return :
     538                but[selected]->animateClick();
     539                e->accept();
     540                break;
     541            case Qt::Key_Right :
     542            case Qt::Key_Left :
     543            case Qt::Key_Up :
     544            case Qt::Key_Down :
     545                but[selected]->highlight(false);
     546                sideButton(but[selected], e->key())->highlight(true);
     547                e->accept();
     548        }
     549    }
     550    if (! e->isAccepted())
     551    {
     552        QFrame::keyPressEvent(e);
     553    }
     554    parentWidget()->setFocus();
    347555}
    348556
     557
     558VKButton::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
     577void VKButton::highlight(bool b)
     578{
     579    setFlat(!b);
     580    setDefault(b);
     581}
     582
     583bool VKButton::isHighlighted()
     584{
     585    return (!isFlat());
     586}
     587
     588void VKButton::setShiftState(bool state)
     589{
     590    if (state) { setText(mykey2); }
     591    else { setText(mykey1); }
     592}
     593
     594void 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
     606void 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
     616void 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
    349653void MythLineEdit::setText(const QString& text)
    350654{
    351655    // Don't mess with the cursor position; it causes
  • libs/libmyth/mythwidgets.h

     
    112112};
    113113
    114114
     115const int popupw = 450;
     116const int popuph = 155;
     117
     118const int alphabuts = 48;
     119const int specialbuts = 7;
     120
     121const int iDone = alphabuts + 0;
     122const int iShift = alphabuts + 1;
     123const int iLock = alphabuts + 2;
     124const int iLeft = alphabuts + 3;
     125const int iRight = alphabuts + 4;
     126const int iBack = alphabuts + 5;
     127const int iDel = alphabuts + 6;
     128
     129class VKButton : public QPushButton
     130{
     131     Q_OBJECT
     132 public:
     133     VKButton( QWidget *parent=0, const char*  name=0, const char* text=0,
     134                  const char* textSh=0, QLineEdit *ebox=0);
     135     void setShiftState(bool state);
     136     void highlight(bool b);
     137     bool isHighlighted();
     138
     139 private slots:
     140     void pressKey();
     141
     142 private:
     143     QString mykey1, mykey2;
     144     QLineEdit *mybox;
     145};
     146
     147
     148class VKPopup : public QFrame
     149{
     150     Q_OBJECT
     151 public:
     152     VKPopup( QWidget *parent=0, const char* name=0 );
     153     ~VKPopup();
     154
     155 protected:
     156     VKButton * sideButton(VKButton * oldbut, int dirkey);
     157     virtual void focusInEvent(QFocusEvent *e);
     158
     159 public slots:
     160     void openPopup();
     161     void closePopup();
     162
     163 private slots:
     164     virtual void keyPressEvent(QKeyEvent *e);
     165     void lockOnOff();
     166     void shiftOnOff();
     167     void shiftOff();
     168
     169 private:
     170     VKButton *but[alphabuts+specialbuts];
     171};
     172
     173
    115174class MythLineEdit : public QLineEdit
    116175{
    117176    Q_OBJECT
    118177  public:
    119178    MythLineEdit(QWidget *parent=NULL, const char* widgetName=0) :
    120       QLineEdit(parent, widgetName) { rw = true; };
    121 
    122     MythLineEdit(const QString& contents, QWidget *parent=NULL,
     179      QLineEdit(parent, widgetName) { rw = true; Init(); }
     180    MythLineEdit(const QString& contents, QWidget *parent=NULL,
    123181                 const char* widgetName=0) :
    124       QLineEdit(contents, parent, widgetName) { rw = true; };
     182      QLineEdit(contents, parent, widgetName) { rw = true; Init(); };
     183    ~MythLineEdit() { if (usevk && popup) { delete popup; } };
    125184
    126185    void setHelpText(QString help) { helptext = help; };
    127186    void setRW(bool readwrite = true) { rw = readwrite; };
     
    129188
    130189 public slots:
    131190     virtual void setText(const QString& text);
     191     void delPressed() { QLineEdit::del(); };
     192     void backPressed() { QLineEdit::backspace(); };
     193     void lCursor() { QLineEdit::cursorBackward(false); };
     194     void rCursor() { QLineEdit::cursorForward(false); };
    132195
    133196  signals:
    134197    void changeHelpText(QString);
    135198
    136199  protected:
     200    void Init();
    137201    virtual void keyPressEvent(QKeyEvent *e);
    138202    virtual void focusInEvent(QFocusEvent *e);
    139203    virtual void focusOutEvent(QFocusEvent *e);
     
    141205  private:
    142206    QString helptext;
    143207    bool rw;
     208    bool usevk;
     209    VKPopup* popup;
    144210};
    145211
    146212// A Line edit that does special things when you press number keys
  • programs/mythfrontend/globalsettings.cpp

     
    10881088    return gc;
    10891089}
    10901090
     1091static HostCheckBox *UseVirtualKeyboard()
     1092{
     1093    HostCheckBox *gc = new HostCheckBox("UseVirtualKeyboard");
     1094    gc->setLabel(QObject::tr("Use line edit virtual keyboards."));
     1095    gc->setValue(true);
     1096    gc->setHelpText(QObject::tr("Whether or not to allow the use of "
     1097                                "virtual keyboards for line edits. Hit "
     1098                                "'select' in a line edit to use."));
     1099    return gc;
     1100}
     1101
    10911102static HostComboBox *AllowQuitShutdown()
    10921103{
    10931104    HostComboBox *gc = new HostComboBox("AllowQuitShutdown");
     
    31343145    qttheme->addChild(QtFontBig());
    31353146    qttheme->addChild(PlayBoxTransparency());
    31363147    qttheme->addChild(PlayBoxShading());
     3148    qttheme->addChild(UseVirtualKeyboard());
    31373149    addChild(qttheme );
    31383150
    31393151    addChild(new LcdSettings());