/** Source : inspired by https://www.kdab.com/qt-input-method-virtual-keyboard/ */ #include "Keyboard.h" #include #include #include #include #include #include #define NEXT_ROW_MARKER '\0' #define SIZE_FACTOR 1 /* looks nice on AGL demo */ //#define SIZE_FACTOR 0.5 /* looks nice on PC build */ #define OFFSET_H ( 78 * SIZE_FACTOR ) #define KEY_WIDTH ( 78 * SIZE_FACTOR ) #define KEY_HEIGHT ( 94 * SIZE_FACTOR ) #define MARGIN_H ( 12 * SIZE_FACTOR ) #define MARGIN_V ( 18 * SIZE_FACTOR ) #define SPACE_BAR_WIDTH ( 502 * SIZE_FACTOR ) struct KeyboardLayoutEntry { int key; const char *image; }; static KeyboardLayoutEntry keyboardLayout[] = { { '1' , "1.png" }, { '2' , "2.png" }, { '3' , "3.png" }, { '4' , "4.png" }, { '5' , "5.png" }, { '6' , "6.png" }, { '7' , "7.png" }, { '8' , "8.png" }, { '9' , "9.png" }, { '0' , "0.png" }, { NEXT_ROW_MARKER, NULL }, { 'q' , "Q.png" }, { 'w' , "W.png" }, { 'e' , "E.png" }, { 'r' , "R.png" }, { 't' , "T.png" }, { 'y' , "Y.png" }, { 'u' , "U.png" }, { 'i' , "I.png" }, { 'o' , "O.png" }, { 'p' , "P.png" }, { NEXT_ROW_MARKER, NULL }, { 'a' , "A.png" }, { 's' , "S.png" }, { 'd' , "D.png" }, { 'f' , "F.png" }, { 'g' , "G.png" }, { 'h' , "H.png" }, { 'j' , "J.png" }, { 'k' , "K.png" }, { 'l' , "L.png" }, { NEXT_ROW_MARKER, NULL }, { 'z' , "Z.png" }, { 'x' , "X.png" }, { 'c' , "C.png" }, { 'v' , "V.png" }, { 'b' , "B.png" }, { 'n' , "N.png" }, { 'm' , "M.png" }, { '!' , "exclam.png" }, { '\b',"back.png" }, { NEXT_ROW_MARKER, NULL }, { '\'',"apostrophe.png" }, { '&' , "et.png" }, { ' ' , "space.png" }, { '-' , "minus.png" }, { '/' , "slash.png" } }; const static int layoutSize = (sizeof(keyboardLayout) / sizeof(KeyboardLayoutEntry)); Keyboard::Keyboard(QRect r, QWidget *parent):QWidget(parent),background(parent), rect(QRect(r.x() + (r.width()-(r.width()*SIZE_FACTOR))/2, r.y(), r.width()*SIZE_FACTOR, r.height()*SIZE_FACTOR)), mapper(new QSignalMapper(this)) { int nbRowMarkers = 1; for (int i = 0; i < layoutSize; ++i) if (keyboardLayout[i].key == NEXT_ROW_MARKER) nbRowMarkers++; connect(mapper, SIGNAL(mapped(int)), SLOT(buttonClicked(int))); int row = 0; int offset_h = KEY_WIDTH; int offset_v = (rect.height() - (KEY_HEIGHT*nbRowMarkers + MARGIN_V*(nbRowMarkers-1))) / 2; background.setGeometry(rect); QImageReader reader(QString(":/images/background.png")); background.setPixmap(QPixmap::fromImage(reader.read()).scaled(rect.width(), rect.height(), Qt::IgnoreAspectRatio)); background.show(); for (int i = 0; i < layoutSize; ++i) { int key_width = KEY_WIDTH; if (keyboardLayout[i].key == NEXT_ROW_MARKER) { row++; offset_h = OFFSET_H; if (row == 2) offset_h += (KEY_WIDTH + MARGIN_H)/2; else if (row == 3) offset_h += (KEY_WIDTH + MARGIN_H); offset_v += (KEY_HEIGHT+MARGIN_V); continue; } else if (keyboardLayout[i].key == ' ') { key_width = SPACE_BAR_WIDTH; } QPushButton *button = new QPushButton(QIcon(tr(":/images/")+QString(keyboardLayout[i].image)), tr(""), &background); button->setMinimumSize(QSize(key_width, KEY_HEIGHT)); button->setMaximumSize(QSize(key_width, KEY_HEIGHT)); button->setIconSize(button->size()); /* geometry of button is relative to its parent, ie 'background' : */ button->setGeometry(QRect(offset_h, offset_v, button->width(), button->height())); button->show(); mapper->setMapping(button, keyboardLayout[i].key); connect(button, SIGNAL(clicked()), mapper, SLOT(map())); offset_h += (key_width+MARGIN_H); } } void Keyboard::buttonClicked(int key) { if (key == '\b') /* backspace */ emit specialKeyClicked(key); else emit keyClicked(QString(key)); } Keyboard::~Keyboard() { disconnect(); delete mapper; }