xref: /OK3568_Linux_fs/app/forlinx/flapp/src/keyboard/keyboard/keyboard.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include "keyboard.h"
2 #include <QPushButton>
3 #include <QSignalMapper>
4 #include <QHBoxLayout>
5 #include <QVBoxLayout>
6 #include <QGridLayout>
7 #include<QCoreApplication>
8 #include <QMap>
9 #include <QKeyEvent>
10 #include <QPainter>
11 #include <QLineEdit>
12 #include <QDebug>
13 #include <QApplication>
14 #include <QTimer>
15 #include <QDebug>
16 #include <QLineEdit>
17 #include <QLabel>
18 #include <QListView>
19 #include "pinyindecoderservice.h"
20 #include "pinyinime.h"
21 #include "keybutton.h"
22 #include "pinyinbar.h"
23 #include <QLoggingCategory>
24 #include <QMouseEvent>
25 Q_LOGGING_CATEGORY(flapp, "app.keyboard")
26 using namespace ime_pinyin;
27 using namespace QtVirtualKeyboard;
28 
Keyboard(QWidget * parent)29 Keyboard::Keyboard(QWidget *parent) :
30     QWidget(parent),
31     m_inputWidget(Q_NULLPTR),
32     m_candidates(0),
33     m_number(0),
34     m_type(0),
35     m_shift(false),
36     m_upper(false)
37 {
38     qApp->setStyle("Fusion");
39    ;
40     setAttribute(Qt::WA_AlwaysStackOnTop);
41     setWindowFlags(Qt::WindowDoesNotAcceptFocus);
42     this->setWindowFlags(Qt::Tool);
43 
44     //设置背景颜色.
45     this->setAutoFillBackground(true);
46     QPalette palette = this->palette();
47     palette.setBrush(QPalette::Background, QColor(242, 242, 242));
48     this->setPalette(palette);
49 
50     QFont f;
51     f.setPixelSize(18);
52     this->setFont(f);
53 
54     createKeys();
55 
56     resetKey();
57 
58     PinyinDecoderService::getInstance()->resetSearch();
59 
60     QApplication *a = dynamic_cast<QApplication*>(QCoreApplication::instance());
61     a->installEventFilter(this);
62     connect(a, &QApplication::focusChanged, this, &Keyboard::foucsChange);
63 }
64 
~Keyboard()65 Keyboard::~Keyboard()
66 {
67 
68 }
69 
createKeys()70 void Keyboard::createKeys()
71 {
72     m_type = 0;
73     m_shift= 0;
74 
75     QVBoxLayout *pVLayout = new QVBoxLayout(this);
76     pVLayout->setContentsMargins(10, 0, 10, 0);
77     pVLayout->setSpacing(0);
78     auto createButtons =[=](QVBoxLayout*pVLayout, int n){
79         QHBoxLayout *pHLayout = new QHBoxLayout;
80         pHLayout->setSpacing(0);
81         for(int i=0; i<n; i++){
82             KeyButton *button = new KeyButton;
83             connect(button, &KeyButton::clicked, this, &Keyboard::handleKey);
84             pHLayout->addWidget(button);
85             m_buttons << button;
86         }
87         pVLayout->addLayout(pHLayout);
88     };
89 
90     QHBoxLayout *pHLayout = new QHBoxLayout;
91     pHLayout->setContentsMargins(10, 0, 10,0);
92     m_bar = new PinyinBar;
93     connect(m_bar, &PinyinBar::textChose, this, &Keyboard::textChose);
94     pHLayout->addWidget(m_bar);
95     pVLayout->addLayout(pHLayout);
96 
97     createButtons(pVLayout, 14);//第一行.
98     createButtons(pVLayout, 14); //第二行.
99     createButtons(pVLayout, 13);//第三行.
100     createButtons(pVLayout, 13);//第四行.
101 }
102 
resetKey()103 void Keyboard::resetKey()
104 {                               //正常键盘显示.
105     static Qt::Key key[2][54] ={Qt::Key_QuoteLeft,  Qt::Key_1, Qt::Key_2,Qt::Key_3,Qt::Key_4,Qt::Key_5,Qt::Key_6,Qt::Key_7,Qt::Key_8,Qt::Key_9, Qt::Key_0,
106                                 Qt::Key_Underscore, Qt::Key_Equal, Qt::Key_Backspace,//14  //第一行.
107 
108                                 Qt::Key_Q, Qt::Key_W,Qt::Key_E,Qt::Key_R,Qt::Key_T,Qt::Key_Y,Qt::Key_U,Qt::Key_I,Qt::Key_O, Qt::Key_P,
109                                 Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Return,Qt::Key_Tab,//14 第二行.
110 
111                                 Qt::Key_CapsLock,  Qt::Key_A, Qt::Key_S,Qt::Key_D,Qt::Key_F,Qt::Key_G,Qt::Key_H,Qt::Key_J,Qt::Key_K,Qt::Key_L, Qt::Key_Semicolon,
112                                 Qt::Key_Apostrophe, Qt::Key_QuoteDbl,//13第三行.
113 
114                                 Qt::Key_Shift,  Qt::Key_Z, Qt::Key_X,Qt::Key_C,Qt::Key_V,Qt::Key_B,Qt::Key_Space, Qt::Key_N,Qt::Key_M, Qt::Key_Comma ,Qt::Key_Period, Qt::Key_Slash,
115                                 Qt::Key_Multi_key,//12第四行.
116 
117                                 //shift 按键切换显示.
118                                 Qt::Key_AsciiTilde, Qt::Key_Exclam, Qt::Key_At, Qt::Key_NumberSign,Qt::Key_Dollar,Qt::Key_Percent,Qt::Key_AsciiCircum,Qt::Key_Ampersand,
119                                 Qt::Key_Asterisk,Qt::Key_ParenLeft, Qt::Key_ParenRight,
120                                 Qt::Key_Minus, Qt::Key_Plus, Qt::Key_Backspace, //14第一行.
121 
122                                 Qt::Key_Q, Qt::Key_W,Qt::Key_E,Qt::Key_R,Qt::Key_T,Qt::Key_Y,Qt::Key_U,Qt::Key_I,Qt::Key_O, Qt::Key_P,
123                                 Qt::Key_BraceLeft, Qt::Key_BraceRight, Qt::Key_Return,Qt::Key_Tab, //14第二行.
124 
125                                 Qt::Key_CapsLock,  Qt::Key_A, Qt::Key_S,Qt::Key_D,Qt::Key_F,Qt::Key_G,Qt::Key_H,Qt::Key_J,Qt::Key_K,Qt::Key_L, Qt::Key_Colon,
126                                 Qt::Key_QuoteDbl, Qt::Key_Bar, //13第三行.
127 
128                                 Qt::Key_Shift,  Qt::Key_Z, Qt::Key_X,Qt::Key_C,Qt::Key_V,Qt::Key_B, Qt::Key_Space, Qt::Key_N,Qt::Key_M,Qt::Key_Less,Qt::Key_Greater, Qt::Key_Question,
129                                 Qt::Key_Multi_key}; //13第四行.
130 
131 
132     for(int i=0; i<54 && i<m_buttons.size(); i++)
133     {
134         Qt::Key k = key[m_shift][i];
135         m_buttons[i]->setKey(k);
136 
137         QString value = getKey(k);
138         m_upper ? value =value.toUpper() :value =value.toLower();
139 
140         m_buttons[i]->setValue(value);
141 
142         //特殊按键替换处理.
143         switch (k) {
144         case Qt::Key_Return:
145             m_buttons[i]->setValue("↵");
146             break;
147 
148         case Qt::Key_Space:
149             m_buttons[i]->setMinimumWidth(60);
150             break;
151 
152         case Qt::Key_Backspace:
153             m_buttons[i]->setValue("←");
154             m_buttons[i]->setAutoRepeat(true);
155             break;
156 
157         case Qt::Key_Tab:
158             m_buttons[i]->setValue("Hide");
159             break;
160 
161         case Qt::Key_CapsLock:
162             m_buttons[i]->setValue("caps");
163             break;
164 
165         case Qt::Key_Shift:
166             m_buttons[i]->setValue("↑");
167             break;
168 
169         case Qt::Key_Multi_key:
170             m_type== 1?  m_buttons[i]->setValue("中"): m_buttons[i]->setValue("en");
171             break;
172         default:
173             break;
174         }
175     }
176 }
177 
getKey(Qt::Key key)178 QString Keyboard::getKey(Qt::Key key)
179 {
180     struct KeyData{
181         QString value[2];  //value[0] 英文字符 value[1] 中文字符.
182         Qt::Key k;
183     };
184     static struct KeyData data[73]={
185                "~", "~", Qt::Key_AsciiTilde,
186                 "!", "!", Qt::Key_Exclam,
187                 "@", "@", Qt::Key_At,
188                 "#", "#", Qt::Key_NumberSign,
189                 "$", "¥", Qt::Key_Dollar,
190                 "%", "%", Qt::Key_Percent,
191                 "^", "……", Qt::Key_AsciiCircum,
192                 "&", "&", Qt::Key_Ampersand,
193                 "*", "*", Qt::Key_Asterisk,
194                 "(", "(", Qt::Key_ParenLeft,
195                 ")", ")", Qt::Key_ParenRight,
196                 "_", "——", Qt::Key_Underscore,
197                 "+", "+", Qt::Key_Plus,
198                 "}", "】", Qt::Key_BraceRight,
199                 "{", "【", Qt::Key_BraceLeft,
200                 "\"", "、", Qt::Key_QuoteDbl,
201                 "|", "|", Qt::Key_Bar,
202                 "?", "?", Qt::Key_Question,
203                 ">", "》", Qt::Key_Greater,
204                 "<", "《", Qt::Key_Less,
205                 "-", "-", Qt::Key_Minus,
206                 "=", "=", Qt::Key_Equal,
207                 "[", "『", Qt::Key_BracketLeft,
208                 "]", "』", Qt::Key_BracketRight,
209                 "\\", "、", Qt::Key_Backslash,
210                 "'", "‘", Qt::Key_Apostrophe,
211                 ";", ";", Qt::Key_Semicolon,
212                 "/", "/", Qt::Key_Slash,
213                 ".", "。", Qt::Key_Period,
214                 ",", ",", Qt::Key_Comma,
215                 "\r","\r", Qt::Key_Return,
216                 "\b", "\b",Qt::Key_Backspace,
217                 " "," ", Qt::Key_Space,
218                 "`", "·", Qt::Key_QuoteLeft,
219                 ":" ,":" ,Qt::Key_Colon,
220                 "P", "P", Qt::Key_P,
221                 "O", "O", Qt::Key_O,
222                 "I", "I", Qt::Key_I,
223                 "U", "U", Qt::Key_U,
224                 "Y", "Y", Qt::Key_Y,
225                 "T", "T", Qt::Key_T,
226                 "R", "R", Qt::Key_R,
227                 "E", "E", Qt::Key_E,
228                 "W", "W", Qt::Key_W,
229                 "Q", "Q", Qt::Key_Q,
230                 "A", "A", Qt::Key_A,
231                 "S", "S", Qt::Key_S,
232                 "D", "D", Qt::Key_D,
233                 "F", "F", Qt::Key_F,
234                 "G", "G", Qt::Key_G,
235                 "H", "H", Qt::Key_H,
236                 "J", "J", Qt::Key_J,
237                 "K", "K", Qt::Key_K,
238                 "L", "L", Qt::Key_L,
239                 "M", "M", Qt::Key_M,
240                 "N", "N", Qt::Key_N,
241                 "B", "B", Qt::Key_B,
242                 "V", "V", Qt::Key_V,
243                 "C", "C", Qt::Key_C,
244                 "X", "X", Qt::Key_X,
245                 "Z", "Z", Qt::Key_Z,
246                 "1", "1", Qt::Key_1,
247                 "2", "2", Qt::Key_2,
248                 "3", "3", Qt::Key_3,
249                 "4", "4", Qt::Key_4,
250                 "5", "5", Qt::Key_5,
251                 "6", "6", Qt::Key_6,
252                 "7", "7", Qt::Key_7,
253                 "8", "8", Qt::Key_8,
254                 "9", "9", Qt::Key_9,
255                 "0", "0", Qt::Key_0,
256                 "",  "", Qt::Key_CapsLock,
257                 " ", " ", Qt::Key_Space
258     };
259 
260     for(int i=0; i<72; i++){
261         KeyData d= data[i];
262         if(d.k == key){
263             return d.value[m_type];
264         }
265     }
266     return "";
267 }
268 
handleKey()269 void Keyboard::handleKey()
270 {
271     KeyButton *button  = dynamic_cast<KeyButton*>(this->sender());
272     if(m_inputWidget && button){
273 
274         switch (button->getKey()) {
275         case Qt::Key_CapsLock:
276             m_upper =!m_upper;
277             resetKey();
278             return;
279 
280         case Qt::Key_Tab:
281             this->setVisible(false);
282             return;
283 
284         case Qt::Key_Shift:
285             m_shift = !m_shift;
286             resetKey();
287             return;
288 
289         case Qt::Key_Multi_key:
290         {
291             if(m_type==0){
292                 m_type =1;
293             }else if(m_type ==1)
294             {
295                 m_type =0;
296             }
297             resetKey();
298         }
299             return;
300         default:
301             break;
302         }
303 
304         if(m_type ==1  && button->getKey()>= Qt::Key_A && button->getKey() <= Qt::Key_Z )
305         {
306             addSearch(button->getValue());
307             return;
308         }else if(button->getKey() == Qt::Key_Backspace && m_bar->count() !=0)
309         {
310             PinyinDecoderService *pinyin =PinyinDecoderService::getInstance();
311             QString str = pinyin->pinyinString(false);
312             clearpinyin();
313             if(str.size()>=1)
314             {
315                 str = str.left(str.size()-1);
316             }
317             addSearch(str);
318             return;
319         }
320 
321         Qt::Key key = button->getKey();
322         QString value =getKey(key);
323         if(!m_upper)
324         {
325             value = value.toLower();
326         }
327 
328         QKeyEvent k(QEvent::KeyPress, key,  Qt::NoModifier, value);
329         qApp->sendEvent(m_inputWidget, &k);
330     }
331 }
332 
hideEvent(QHideEvent * event)333 void Keyboard::hideEvent(QHideEvent *event)
334 {
335     QWidget::hideEvent(event);
336     clearpinyin();
337     addSearch();
338 }
339 
clearpinyin()340 void Keyboard::clearpinyin()
341 {
342     PinyinDecoderService *pinyin =PinyinDecoderService::getInstance();
343     QString str =pinyin->pinyinString(false);
344     for(int i=0; i<str.size(); i++)
345     {
346         pinyin->deleteSearch(0, true, true);
347     }
348 }
349 
addSearch(const QString & s)350 void Keyboard::addSearch(const QString &s)
351 {
352     PinyinDecoderService *pinyin =PinyinDecoderService::getInstance();
353     QString d =pinyin->pinyinString(false);
354     qCDebug(flapp)<<"search str ="<< d;
355     if(s.isEmpty())
356     {
357         if(!d.isEmpty())
358         {
359             m_candidates = pinyin->search(d);
360         }
361     }else{
362         m_candidates = pinyin->search(d + s);
363     }
364     QList<QString> candList = pinyin->fetchCandidates(0, m_candidates, 0);
365 
366     qCDebug(flapp)<<"search list ="<< candList.size();
367     QStringList list (candList);
368     list.removeAll("");
369     m_bar->setStringList(list, pinyin->pinyinString(false));
370     if(list.isEmpty())
371     {
372          clearpinyin();
373     }
374 }
375 
textChose(const QString & text,int index)376 void Keyboard::textChose(const QString &text, int index)
377 {
378     qCDebug(flapp)<<"textChose : text ="<< text << " index ="<< index;
379 
380     static PinyinDecoderService *pinyin =PinyinDecoderService::getInstance();
381     QVector<int>vec =pinyin->spellingStartPositions();
382     if(vec.size() >0)
383     qCDebug(flapp)<< "count="<<vec.size() << "vec[0]="<< vec[0];
384     if(vec.size() >0  && m_number < vec[0])
385     {
386         pinyin->chooceCandidate(index);
387         QList<QString> candList = pinyin->fetchCandidates(0, m_candidates, 0);
388         m_list = QStringList(candList);
389         m_bar->setStringList(m_list, pinyin->pinyinString(false));
390         QString data = text;
391         if(data.size() == vec[0])
392         {
393             data = data.right(data.size()-m_number);
394             m_number =vec[0];
395         }else{
396             m_number += text.size();
397         }
398         QKeyEvent k(QEvent::KeyPress, Qt::Key_MultipleCandidate, Qt::NoModifier, data);
399         qApp->sendEvent(m_inputWidget, &k);
400         if(m_number == vec[0]){
401             m_number =0;
402             m_bar->setStringList(QStringList());
403             clearpinyin();
404             qCDebug(flapp)<<"reset search";
405         }
406     }
407 }
408 
eventFilter(QObject * watched,QEvent * event)409 bool Keyboard::eventFilter(QObject *watched, QEvent *event)
410 {
411     switch (event->type()) {
412 //    case QEvent::FocusIn:
413 //    {
414 //        QWidget *now = dynamic_cast<QWidget*>(watched);
415 //        QFocusEvent *foucsEvent = dynamic_cast<QFocusEvent*>(event);
416 //        if(hasInput(now) && foucsEvent->reason() == Qt::MouseFocusReason)
417 //        {
418 //            if(m_inputWidget != Q_NULLPTR){
419 //                m_inputWidget->removeEventFilter(this);
420 //                this->disconnect(this);
421 //            }
422 //            now->installEventFilter(this);
423 //            m_inputWidget = now;
424 //            resizeWidget(m_inputWidget);
425 //            setVisible(true);
426 
427 //        }
428 
429 //    }break;
430 
431     case QEvent::Destroy:
432     {
433        if(watched == m_inputWidget){
434            setParent(Q_NULLPTR);
435            m_inputWidget = Q_NULLPTR;
436        }
437 
438     }break;
439     case QEvent::MouseButtonPress:
440     {
441         QMouseEvent *mouseEvent =dynamic_cast<QMouseEvent*>(event);
442        if(watched == m_inputWidget&&mouseEvent->button() == Qt::LeftButton  && hasInput(m_inputWidget))
443        {
444            this->resizeWidget(m_inputWidget);
445            this->setVisible(true);
446            event->accept();
447            return true;
448        }
449 
450     }break;
451 
452     case QEvent::Resize:
453     {
454        if(watched == this)
455        {
456            resizeWidget(m_inputWidget);
457            event->accept();
458            return true;
459        }
460     }break;
461 
462     case QEvent::WindowDeactivate:
463     {
464         if(watched == qApp)
465         {
466             qApp->activeWindow()->clearFocus();
467         }
468     }break;
469     default:
470         break;
471     }
472 
473     return QWidget::eventFilter(watched, event);
474 }
475 
resizeWidget(QWidget * w)476 void Keyboard::resizeWidget(QWidget *w)
477 {
478     QWidget *topWidget = w->topLevelWidget();
479     setParent(topWidget);
480 
481     int width = topWidget->width();
482     int height = topLevelWidget()->height()/3;
483     if(height< 150){
484         height =150;
485     }
486     //输入控件在位置比最顶层父窗口位置一半大, 显示在最顶层窗口哦上面,否则显示在最顶层窗口底部.
487     QPoint pos = w->mapTo(topWidget, w->pos());
488     qCDebug(flapp)<<"input widget pos: "<< w->pos() << "global pos: "<< pos << "window rect: s" << topWidget->rect();
489 
490     if(pos.y() <= topWidget->height()/2){
491         this->setGeometry(0,topWidget->height() -height-20, width, height);
492     }else{
493         this->setGeometry(0,20, width, height);
494     }
495 }
496 
hasInput(QWidget * w)497 bool Keyboard::hasInput(QWidget *w)
498 {
499     bool bRet =false;
500     //过滤 QListView 输入,防止QComboBox上显示键盘.
501     if(w != Q_NULLPTR && dynamic_cast<QAbstractItemView*>(w))
502         return bRet;
503 
504     //所有输入控件必须有WA_InputMethodEnabled 属性方可显示.
505     if(w!= Q_NULLPTR
506             && w->isEnabled()
507             &&w->testAttribute(Qt::WA_InputMethodEnabled))
508     {
509         bRet =true;
510     }
511 
512     return bRet;
513 }
514 
foucsChange(QWidget * old,QWidget * now)515 void Keyboard::foucsChange(QWidget *old, QWidget *now)
516 {
517     Q_UNUSED(old)
518     if(hasInput(now))
519     {
520         if(m_inputWidget != Q_NULLPTR){
521             m_inputWidget->removeEventFilter(this);
522             m_inputWidget->topLevelWidget()->removeEventFilter(this);
523             this->disconnect(this);
524         }
525         now->installEventFilter(this);
526         m_inputWidget = now;
527         resizeWidget(m_inputWidget);
528         setVisible(true);
529 
530     }
531 }
532 
533