1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 2000-2014 Licq developers <licq-dev@googlegroups.com>
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include "selectemoticon.h"
21 
22 #include <math.h>
23 
24 #include <QGridLayout>
25 #include <QKeyEvent>
26 #include <QMap>
27 
28 #include "config/emoticons.h"
29 
30 #include "helpers/support.h"
31 
32 using namespace LicqQtGui;
33 
EmoticonLabel(const QString & file,const QString & value,QWidget * parent)34 EmoticonLabel::EmoticonLabel(const QString& file, const QString& value, QWidget* parent)
35   : QPushButton(parent),
36     myValue(value)
37 {
38   QPixmap icon = QPixmap(file);
39   setIconSize(icon.size());
40   setIcon(icon);
41   setToolTip(value);
42   setFixedSize(icon.size() + QSize(10, 10));
43   setFlat(true);
44 }
45 
mouseReleaseEvent(QMouseEvent *)46 void EmoticonLabel::mouseReleaseEvent(QMouseEvent* /* e */)
47 {
48   if (underMouse())
49     emit clicked(myValue);
50 }
51 
keyPressEvent(QKeyEvent * e)52 void EmoticonLabel::keyPressEvent(QKeyEvent* e)
53 {
54   if (e->modifiers() != Qt::NoModifier)
55     return;
56 
57   switch (e->key())
58   {
59     case Qt::Key_Return: // Fall through
60     case Qt::Key_Enter:
61     case Qt::Key_Space:
62       emit clicked(myValue);
63       break;
64 
65     case Qt::Key_Up: // Fall through
66     case Qt::Key_Down:
67       emit move(this, e->key());
68       break;
69 
70     default:
71       QPushButton::keyPressEvent(e);
72       break;
73   }
74 }
75 
SelectEmoticon(QWidget * parent)76 SelectEmoticon::SelectEmoticon(QWidget* parent)
77   : QFrame(parent, Qt::Popup)
78 {
79   Support::setWidgetProps(this, "SelectEmoticon");
80   setAttribute(Qt::WA_DeleteOnClose, true);
81 
82   setFrameShape(StyledPanel);
83 
84   QMap<QString, QString> map = Emoticons::self()->emoticonsKeys();
85   QMap<QString, QString>::iterator iter;
86 
87   int nCols = static_cast<int>(sqrt(map.size()));
88 
89   grid = new QGridLayout(this);
90   grid->setContentsMargins(0, 0, 0, 0);
91   grid->setSpacing(0);
92 
93   int x = 0, y = 0;
94   for (iter = map.begin(); iter != map.end(); ++iter)
95   {
96     EmoticonLabel* lbl = new EmoticonLabel(iter.key(), iter.value(), this);
97 
98     connect(lbl, SIGNAL(clicked(const QString&)), SLOT(emoticonClicked(const QString&)));
99     connect(lbl, SIGNAL(move(EmoticonLabel*, int)), SLOT(moveFrom(EmoticonLabel*, int)));
100 
101     grid->addWidget(lbl, y, x++);
102     grid->setAlignment(lbl, Qt::AlignCenter);
103 
104     // Set the focus to the first item so we can use the keyboard to navigate
105     if (y == 0 && x == 1)
106       lbl->setFocus();
107 
108     if (x == nCols)
109     {
110       x = 0;
111       y++;
112     }
113   }
114 }
115 
emoticonClicked(const QString & value)116 void SelectEmoticon::emoticonClicked(const QString& value)
117 {
118   emit selected(value);
119   close();
120 }
121 
moveFrom(EmoticonLabel * item,int key)122 void SelectEmoticon::moveFrom(EmoticonLabel* item, int key)
123 {
124   if (item == 0)
125     return;
126 
127   int index = grid->indexOf(item);
128 
129   switch (key)
130   {
131     case Qt::Key_Up:
132       index -= grid->columnCount();
133       if (index < 0)
134         index += grid->columnCount() * grid->rowCount();
135       while (grid->itemAt(index) == 0)
136         index -= grid->columnCount();
137       break;
138 
139     case Qt::Key_Down:
140       index += grid->columnCount();
141       while (grid->itemAt(index) == 0)
142         if (index >= grid->columnCount() * grid->rowCount())
143           index -= grid->columnCount() * grid->rowCount();
144         else
145           index += grid->columnCount();
146       break;
147 
148     default:
149       return;
150   }
151 
152   grid->itemAt(index)->widget()->setFocus();
153 }
154