Projet e-stok  0.2
BTS SNIR LaSalle Avignon 2020
Keyboard.cpp
Aller à la documentation de ce fichier.
1 
9 #include "Keyboard.h"
10 
11 #include <QGridLayout>
12 #include <QSignalMapper>
13 #include <QPushButton>
14 #include <QDebug>
15 
16 #define NEXT_ROW_MARKER 0
17 
19 {
20  int key;
21  const char *label;
23  const char *labelCapsLock;
24 };
25 
26 KeyboardLayoutEntry keyboardLayout[] =
27 {
28  { Qt::Key_1, "1", Qt::Key_Ampersand, "&" },
29  { Qt::Key_2, "2", Qt::Key_Eacute, "é" },
30  { Qt::Key_3, "3", Qt::Key_QuoteDbl, "\"" },
31  { Qt::Key_4, "4", Qt::Key_Apostrophe, "'" },
32  { Qt::Key_5, "5", Qt::Key_ParenRight, "(" },
33  { Qt::Key_6, "6", Qt::Key_hyphen, "-" },
34  { Qt::Key_7, "7", Qt::Key_Egrave, "è" },
35  { Qt::Key_8, "8", Qt::Key_Underscore, "_" },
36  { Qt::Key_9, "9", Qt::Key_cedilla, "ç" },
37  { Qt::Key_0, "0", Qt::Key_Agrave, "à" },
38  { Qt::Key_Percent, "%", Qt::Key_ParenLeft, ")" },
39  { Qt::Key_Plus, "+", Qt::Key_Equal, "=" },
40  { Qt::Key_Backspace, "<-", Qt::Key_Backspace, "<-"},
41  { NEXT_ROW_MARKER, 0, 0, 0 },
42  { Qt::Key_A, "a", Qt::Key_A, "A" },
43  { Qt::Key_Z, "z", Qt::Key_Z, "Z" },
44  { Qt::Key_E, "e", Qt::Key_E, "E" },
45  { Qt::Key_R, "r", Qt::Key_R, "R" },
46  { Qt::Key_T, "t", Qt::Key_T, "T" },
47  { Qt::Key_Y, "y", Qt::Key_Y, "Y" },
48  { Qt::Key_U, "u", Qt::Key_U, "U" },
49  { Qt::Key_I, "i", Qt::Key_I, "I" },
50  { Qt::Key_O, "o", Qt::Key_O, "O" },
51  { Qt::Key_P, "p", Qt::Key_P, "P" },
52  { Qt::Key_At, "@", Qt::Key_Dollar, "$" },
53  { Qt::Key_Escape, "Esc", Qt::Key_Escape, "Esc" },
54  { Qt::Key_Delete, "X", Qt::Key_Delete, "X"},
55  { NEXT_ROW_MARKER, 0, 0, 0 },
56  { Qt::Key_Q, "q", Qt::Key_Q, "Q" },
57  { Qt::Key_S, "s", Qt::Key_S, "S" },
58  { Qt::Key_D, "d", Qt::Key_D, "D" },
59  { Qt::Key_F, "f", Qt::Key_F, "F" },
60  { Qt::Key_G, "g", Qt::Key_G, "G" },
61  { Qt::Key_H, "h", Qt::Key_H, "H" },
62  { Qt::Key_J, "j", Qt::Key_J, "J" },
63  { Qt::Key_K, "k", Qt::Key_K, "K" },
64  { Qt::Key_L, "l", Qt::Key_L, "L" },
65  { Qt::Key_M, "m", Qt::Key_M, "M" },
66  { Qt::Key_Ooblique, "/", Qt::Key_Backslash, "\\" },
67  { Qt::Key_multiply, "*", Qt::Key_ssharp, "#" },
68  { Qt::Key_Space, " ", Qt::Key_Space, " " },
69  { NEXT_ROW_MARKER, 0, 0, 0 },
70  { Qt::Key_CapsLock, "Maj", Qt::Key_CapsLock, "Maj" },
71  { Qt::Key_Less, "<", Qt::Key_Greater, ">" },
72  { Qt::Key_W, "w", Qt::Key_W, "W"},
73  { Qt::Key_X, "x", Qt::Key_X, "X"},
74  { Qt::Key_C, "c", Qt::Key_C, "C"},
75  { Qt::Key_V, "v", Qt::Key_V, "V"},
76  { Qt::Key_B, "b", Qt::Key_B, "B"},
77  { Qt::Key_N, "n", Qt::Key_N, "N"},
78  { Qt::Key_Comma, ",", Qt::Key_Question, "?"},
79  { Qt::Key_Semicolon, ";", Qt::Key_Period, "."},
80  { Qt::Key_Colon, ":", Qt::Key_AsciiTilde, "~"},
81  { Qt::Key_exclamdown, "!", Qt::Key_section, "§"},
82  { Qt::Key_Enter, "Entrée", Qt::Key_Enter, "Entrée"}
83 };
84 
85 const static int layoutSize = (sizeof(keyboardLayout) / sizeof(KeyboardLayoutEntry));
86 
87 #ifdef KEYBOARD_SINGLETON
88 Keyboard* Keyboard::instance = Q_NULLPTR;
89 
90 Keyboard* Keyboard::getInstance(QLineEdit *lineEdit, QWidget *parent)
91 {
92  if(instance == Q_NULLPTR)
93  {
94  instance = new Keyboard(lineEdit, parent);
95  }
96  return instance;
97 }
98 #endif
99 
100 Keyboard::Keyboard(QLineEdit *lineEdit, QWidget *parent) : QWidget(parent), lineEdit(lineEdit), capsLock(false), mask(false)
101 {
102 #ifdef DEBUG_KEYBOARD
103  qDebug() << Q_FUNC_INFO << this << lineEdit;
104 #endif
105  init();
106  connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(focusChange(QWidget*,QWidget*)));
107  connect(this, SIGNAL(keyClicked(QString)), this, SLOT(keyboardKeyClicked(QString)));
108  connect(this, SIGNAL(specialKeyClicked(int)), this, SLOT(keyboardSpecialKeyClicked(int)));
109  setStyleSheet("/*QWidget{background-color:white;}*/QPushButton{font-family:\"Ubuntu Mono\";font:bold;font-size:16px;background-color:palegoldenrod;border-width:1px;border-color:darkkhaki;border-style:solid;border-radius:5;padding:1px;}QPushButton:hover{background-color:khaki;}QPushButton:pressed{background-color:#d0d67c;}");
110  setAttribute(Qt::WA_TranslucentBackground, true);
111 }
112 
113 void Keyboard::paintEvent(QPaintEvent *e)
114 {
115  QPainter painter(this);
116  QPen pen;
117  pen.setBrush(QBrush(QColor(128, 128, 128, 64)));
118  painter.setPen(pen);
119  painter.drawRoundedRect(0,0,width()-1, height()-1,5,5);
120  QWidget::paintEvent(e);
121 }
122 
124 {
125  if(lineEdit && this->lineEdit != lineEdit)
126  {
127 #ifdef DEBUG_KEYBOARD
128  qDebug() << Q_FUNC_INFO << this << lineEdit;
129 #endif
130  this->lineEdit = lineEdit;
131  capsLock = false;
132  mask = false;
133  }
134 }
135 
136 void Keyboard::showKeyboard(int globalX, int globalY)
137 {
138  QWidget::move(globalX, globalY);
139  if(mask)
140  {
141  setFixedSize(hBoxLayout->sizeHint());
142  stackedWidget->setCurrentIndex(1);
143  }
144  else
145  {
146  setFixedSize(gridLayout->sizeHint());
147  stackedWidget->setCurrentIndex(0);
148  }
149  QWidget::show();
150 }
151 
153 {
154  QWidget::hide();
155 }
156 
158 {
159  return QWidget::isVisible();
160 }
161 
163 {
164 #ifdef DEBUG_KEYBOARD
165  qDebug() << Q_FUNC_INFO << key;
166 #endif
167  if ((key == Qt::Key_Escape))
168  {
169  mask = !mask;
170  if(mask)
171  {
172  setFixedSize(hBoxLayout->sizeHint());
173  stackedWidget->setCurrentIndex(1);
174  }
175  else
176  {
177  setFixedSize(gridLayout->sizeHint());
178  stackedWidget->setCurrentIndex(0);
179  }
180  return;
181  }
182  if ((key == Qt::Key_CapsLock))
183  {
184  capsLock = !capsLock;
185  makeCapsLock();
186  return;
187  }
188  if ((key == Qt::Key_Delete))
189  {
190  if(lineEdit)
191  lineEdit->clear();
192  return;
193  }
194  if ((key == Qt::Key_Enter) || (key == Qt::Key_Backspace))
195  {
196  emit specialKeyClicked(key);
197  }
198  else
199  {
200  emit keyClicked(keyToCharacter(key));
201  }
202 }
203 
204 void Keyboard::focusChange(QWidget* oldWidget, QWidget* newWidget)
205 {
206  if(!lineEdit || !newWidget)
207  return;
208 #ifdef DEBUG_KEYBOARD
209  qDebug() << Q_FUNC_INFO << oldWidget << newWidget;
210 #endif
211  if(newWidget == lineEdit)
212  {
213  QPoint globalPos(0, 0);
214  globalPos = newWidget->mapToGlobal(QPoint(0, newWidget->height()));
215  showKeyboard(globalPos.x(), globalPos.y());
216  }
217  else
218  {
219  hideKeyboard();
220  }
221 }
222 
224 {
225 #ifdef DEBUG_KEYBOARD
226  qDebug() << Q_FUNC_INFO << this << key;
227 #endif
228  if (!lineEdit)
229  return;
230 
231  if (key == Qt::Key_Enter)
232  {
233  QKeyEvent *pressEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
234  QGuiApplication::postEvent(lineEdit, pressEvent);
235 
236  QKeyEvent *releaseEvent = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier);
237  QGuiApplication::postEvent(lineEdit, releaseEvent);
238  }
239  else if (key == Qt::Key_Backspace)
240  {
241  QKeyEvent *pressEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
242  QGuiApplication::postEvent(lineEdit, pressEvent);
243 
244  QKeyEvent *releaseEvent = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier);
245  QGuiApplication::postEvent(lineEdit, releaseEvent);
246  }
247 }
248 
249 void Keyboard::keyboardKeyClicked(const QString &characters)
250 {
251 #ifdef DEBUG_KEYBOARD
252  qDebug() << Q_FUNC_INFO << lineEdit << characters;
253 #endif
254  if (!lineEdit)
255  return;
256 
257  QInputMethodEvent event;
258  event.setCommitString(characters);
259 
260  QGuiApplication::sendEvent(lineEdit, &event);
261 }
262 
264 {
265  setWindowFlags(Qt::WindowDoesNotAcceptFocus | Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint);
266 
267  stackedWidget = new QStackedWidget(this);
268  QWidget *widgetKeyboard = new QWidget(stackedWidget);
269  QWidget *widgetMask = new QWidget(stackedWidget);
270 
271  gridLayout = new QGridLayout(widgetKeyboard);
272  hBoxLayout = new QHBoxLayout(widgetMask);
273 
274  mapper = new QSignalMapper(this);
275  connect(mapper, SIGNAL(mapped(int)), SLOT(buttonClicked(int)));
276 
277  int row = 0;
278  int column = 0;
279 
280  for (int i = 0; i < layoutSize; ++i)
281  {
282  if (keyboardLayout[i].key == NEXT_ROW_MARKER)
283  {
284  row++;
285  column = 0;
286  continue;
287  }
288 
289  QPushButton *button = new QPushButton(this);
290  if (keyboardLayout[i].key == Qt::Key_Enter)
291  button->setFixedWidth(55);
292  else
293  button->setFixedWidth(35);
294  button->setFixedHeight(25);
295  button->setText(QString::fromUtf8(keyboardLayout[i].label));
296 
297  mapper->setMapping(button, keyboardLayout[i].key);
298  connect(button, SIGNAL(clicked()), mapper, SLOT(map()));
299 
300  if (keyboardLayout[i].key == Qt::Key_Escape)
301  {
302  buttonEsc = new QPushButton(this);
303  buttonEsc->setFixedWidth(35);
304  buttonEsc->setText(QString::fromUtf8(keyboardLayout[i].label));
305  mapper->setMapping(buttonEsc, keyboardLayout[i].key);
306  connect(buttonEsc, SIGNAL(clicked()), mapper, SLOT(map()));
307  hBoxLayout->addWidget(buttonEsc);
308  }
309  gridLayout->addWidget(button, row, column);
310  column++;
311  }
312  widgetMask->setFixedSize(hBoxLayout->sizeHint());
313  stackedWidget->addWidget(widgetKeyboard);
314  stackedWidget->addWidget(widgetMask);
315 }
316 
318 {
319  int row = 0;
320  int column = 0;
321  for (int i = 0; i < layoutSize; ++i)
322  {
323  if (keyboardLayout[i].key == NEXT_ROW_MARKER)
324  {
325  row++;
326  column = 0;
327  continue;
328  }
329 
330  QPushButton *button = dynamic_cast<QPushButton*>(gridLayout->itemAtPosition(row, column)->widget());
331  if(capsLock)
332  {
333  mapper->setMapping(button, keyboardLayout[i].keyCapsLock);
334  button->setText(QString::fromUtf8(keyboardLayout[i].labelCapsLock));
335  }
336  else
337  {
338  mapper->setMapping(button, keyboardLayout[i].key);
339  button->setText(QString::fromUtf8(keyboardLayout[i].label));
340  }
341  column++;
342  }
343 }
344 
345 QString Keyboard::keyToCharacter(int key)
346 {
347  for (int i = 0; i < layoutSize; ++i)
348  {
349  if (keyboardLayout[i].key == key)
350  {
351  if(capsLock)
352  return QString::fromUtf8(keyboardLayout[i].labelCapsLock);
353  else
354  return QString::fromUtf8(keyboardLayout[i].label);
355  }
356  else if (keyboardLayout[i].keyCapsLock == key)
357  return QString::fromUtf8(keyboardLayout[i].labelCapsLock);
358  }
359 
360  return QString();
361 }
const char * labelCapsLock
Definition: Keyboard.cpp:23
Déclaration de la classe Keyboard.
Definition: Keyboard.h:22
void paintEvent(QPaintEvent *e)
Definition: Keyboard.cpp:113
QSignalMapper * mapper
Definition: Keyboard.h:33
bool capsLock
Definition: Keyboard.h:36
QGridLayout * gridLayout
Definition: Keyboard.h:31
static Keyboard * getInstance(QWidget *parent=Q_NULLPTR)
void setLineEdit(QLineEdit *lineEdit)
Definition: Keyboard.cpp:123
QStackedWidget * stackedWidget
Definition: Keyboard.h:30
QPushButton * buttonEsc
Definition: Keyboard.h:35
void showKeyboard(int globalX, int globalY)
Definition: Keyboard.cpp:136
void buttonClicked(int key)
Definition: Keyboard.cpp:162
QLineEdit * lineEdit
Definition: Keyboard.h:34
void keyboardSpecialKeyClicked(int key)
Definition: Keyboard.cpp:223
#define NEXT_ROW_MARKER
Definition: Keyboard.cpp:16
Fichier qui contient la déclaration de la classe Keyboard.
void focusChange(QWidget *, QWidget *)
Definition: Keyboard.cpp:204
void makeCapsLock()
Definition: Keyboard.cpp:317
QHBoxLayout * hBoxLayout
Definition: Keyboard.h:32
Definition: Keyboard.cpp:18
bool mask
Definition: Keyboard.h:37
void hideKeyboard()
Definition: Keyboard.cpp:152
KeyboardLayoutEntry keyboardLayout[]
Definition: Keyboard.cpp:26
int keyCapsLock
Definition: Keyboard.cpp:22
void init()
Definition: Keyboard.cpp:263
void keyClicked(const QString &text)
bool keyboardVisible() const
Definition: Keyboard.cpp:157
static const int layoutSize
Definition: Keyboard.cpp:85
QString keyToCharacter(int key)
Definition: Keyboard.cpp:345
const char * label
Definition: Keyboard.cpp:21
void specialKeyClicked(int key)
Keyboard(QLineEdit *lineEdit=Q_NULLPTR, QWidget *parent=Q_NULLPTR)
Definition: Keyboard.cpp:100
void keyboardKeyClicked(const QString &characters)
Definition: Keyboard.cpp:249
int key
Definition: Keyboard.cpp:20