00001 #include <qpixmap.h>
00002 #include <qimage.h>
00003 #include <qapplication.h>
00004
00005 #include "virtualkeyboard.h"
00006 #include "mythcontext.h"
00007 #include "mythdialogs.h"
00008 #include "uitypes.h"
00009
00010 #define LOC QString("VirtualKeyboard: ")
00011 #define LOC_WARN QString("VirtualKeyboard, Warning: ")
00012 #define LOC_ERR QString("VirtualKeyboard, Error: ")
00013
00014 VirtualKeyboard::VirtualKeyboard(MythMainWindow *parent,
00015 QWidget *parentEdit,
00016 const char *name,
00017 bool setsize)
00018 : MythThemedDialog(parent, name, setsize)
00019 {
00020 setFrameStyle(QFrame::Panel | QFrame::Raised);
00021 setLineWidth(1);
00022 m_parentEdit = parentEdit;
00023
00024 SwitchLayout(gContext->GetLanguageAndVariant());
00025 }
00026
00027 void VirtualKeyboard::SwitchLayout(const QString &lang)
00028 {
00029 if (!m_parentEdit)
00030 {
00031 VERBOSE(VB_IMPORTANT, LOC_ERR + "No edit receiving output");
00032 reject();
00033 return;
00034 }
00035
00036 QString language = lang.lower();
00037
00038
00039 if (language.left(2) == "en")
00040 {
00041 if (language.contains("en_gb", false))
00042 {
00043 language = "en_uk";
00044 }
00045 else
00046 {
00047 language = "en_us";
00048 }
00049 }
00050
00051 QString theme_file = QString("keyboard/%1_").arg(language);
00052
00053 if (!loadThemedWindow("keyboard", theme_file))
00054 {
00055 VERBOSE(VB_GENERAL, LOC_WARN +
00056 QString("Cannot find layout for '%1'").arg(language));
00057
00058
00059 if (!loadThemedWindow("keyboard", "keyboard/en_us_"))
00060 {
00061 VERBOSE(VB_IMPORTANT, LOC_ERR +
00062 "Cannot find layout for US English");
00063
00064 reject();
00065 return;
00066 }
00067 }
00068
00069
00070 LayerSet *container = getContainer("keyboard_container");
00071
00072 if (!container)
00073 {
00074 VERBOSE(VB_IMPORTANT, LOC_ERR +
00075 "Cannot find the 'keyboard_container' in your theme");
00076
00077 reject();
00078 return;
00079 }
00080
00081 m_popupWidth = container->GetAreaRect().width();
00082 m_popupHeight = container->GetAreaRect().height();
00083 setFixedSize(QSize(m_popupWidth, m_popupHeight));
00084
00085 QWidget *pw = m_parentEdit;
00086 QWidget *tlw = pw->topLevelWidget();
00087 QRect pwg = pw->geometry();
00088 QRect tlwg = tlw->frameGeometry();
00089
00090 QPoint newpos;
00091
00092 PopupPosition preferredPos;
00093 if (m_parentEdit->inherits("MythLineEdit"))
00094 {
00095 MythLineEdit *par = (MythLineEdit *)m_parentEdit;
00096 preferredPos = par->getPopupPosition();
00097 }
00098 else if (m_parentEdit->inherits("MythRemoteLineEdit"))
00099 {
00100 MythRemoteLineEdit *par = (MythRemoteLineEdit *)m_parentEdit;
00101 preferredPos = par->getPopupPosition();
00102 }
00103 else if (m_parentEdit->inherits("MythComboBox"))
00104 {
00105 MythComboBox *par = (MythComboBox *)m_parentEdit;
00106 preferredPos = par->getPopupPosition();
00107 }
00108 else
00109 {
00110 preferredPos = VK_POSCENTERDIALOG;
00111 }
00112
00113 if (preferredPos == VK_POSBELOWEDIT)
00114 {
00115 if (pw->mapTo(tlw, QPoint(0,pwg.height() + m_popupHeight + 5)).y()
00116 < tlwg.height())
00117 {
00118 newpos = QPoint(pwg.width() / 2 - m_popupWidth / 2, pwg.height() + 5);
00119 }
00120 else
00121 {
00122 newpos = QPoint(pwg.width() / 2 - m_popupWidth / 2, - 5 - m_popupHeight);
00123 }
00124 }
00125 else if (preferredPos == VK_POSABOVEEDIT)
00126 {
00127 if (pw->mapTo(tlw, QPoint(0, - m_popupHeight - 5)).y()
00128 > 0)
00129 {
00130 newpos = QPoint(pwg.width() / 2 - m_popupWidth / 2, - 5 - m_popupHeight);
00131 }
00132 else
00133 {
00134 newpos = QPoint(pwg.width() / 2 - m_popupWidth / 2, pwg.height() + 5);
00135 }
00136 }
00137 else if (preferredPos == VK_POSTOPDIALOG)
00138 {
00139 newpos = QPoint(tlwg.width() / 2 - m_popupWidth / 2, 5);
00140 this->move(newpos);
00141 }
00142 else if (preferredPos == VK_POSBOTTOMDIALOG)
00143 {
00144 newpos = QPoint(tlwg.width() / 2 - m_popupWidth / 2,
00145 tlwg.height() - 5 - m_popupHeight);
00146 this->move(newpos);
00147 }
00148 else if (preferredPos == VK_POSCENTERDIALOG)
00149 {
00150 newpos = QPoint(tlwg.width() / 2 - m_popupWidth / 2,
00151 tlwg.height() / 2 - m_popupHeight / 2);
00152 this->move(newpos);
00153 }
00154
00155 if (preferredPos == VK_POSABOVEEDIT || preferredPos == VK_POSBELOWEDIT)
00156 {
00157 int delx = pw->mapTo(tlw,newpos).x() + m_popupWidth - tlwg.width() + 5;
00158 newpos = QPoint(newpos.x() - (delx > 0 ? delx : 0), newpos.y());
00159 delx = pw->mapTo(tlw, newpos).x();
00160 newpos = QPoint(newpos.x() - (delx < 0 ? delx : 0), newpos.y());
00161
00162 int xbase, width, ybase, height;
00163 float wmult, hmult;
00164 gContext->GetScreenSettings(xbase, width, wmult, ybase, height, hmult);
00165 newpos.setX(newpos.x() - xbase);
00166 newpos.setY(newpos.y() - ybase);
00167
00168 this->move( pw->mapToGlobal( newpos ) );
00169 }
00170
00171
00172 m_keyboard = getUIKeyboardType("keyboard");
00173 if (!m_keyboard)
00174 {
00175 VERBOSE(VB_IMPORTANT, LOC_ERR +
00176 "Cannot find the UIKeyboardType in your theme");
00177
00178 reject();
00179 return;
00180 }
00181
00182 if (m_parentEdit->inherits("QComboBox"))
00183 {
00184 QComboBox *combo = (QComboBox *) m_parentEdit;
00185 m_keyboard->SetEdit(combo->lineEdit());
00186 }
00187 else
00188 m_keyboard->SetEdit(m_parentEdit);
00189
00190 m_keyboard->SetParentDialog(this);
00191 }
00192
00193 VirtualKeyboard::~VirtualKeyboard(void)
00194 {
00195 Teardown();
00196 }
00197
00198 void VirtualKeyboard::deleteLater(void)
00199 {
00200 Teardown();
00201 }
00202
00203 void VirtualKeyboard::Teardown(void)
00204 {
00205 m_keyboard = NULL;
00206 m_parentEdit = NULL;
00207 }
00208
00209 void VirtualKeyboard::Show(void)
00210 {
00211 grabKeyboard();
00212
00213 MythDialog::Show();
00214
00215 if (m_parentEdit)
00216 m_parentEdit->setFocus();
00217 }
00218
00219 void VirtualKeyboard::hide()
00220 {
00221 releaseKeyboard();
00222
00223 if (m_parentEdit)
00224 m_parentEdit->setFocus();
00225
00226 MythDialog::hide();
00227 }
00228
00229 void VirtualKeyboard::keyPressEvent(QKeyEvent *e)
00230 {
00231 bool handled = false;
00232 QStringList actions;
00233 if (gContext->GetMainWindow()->TranslateKeyPress("qt", e, actions, false))
00234 {
00235 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00236 {
00237 QString action = actions[i];
00238 handled = true;
00239 if (action == "ESCAPE")
00240 accept();
00241 else
00242 handled = false;
00243 }
00244 }
00245
00246
00247 if (!handled && m_keyboard)
00248 m_keyboard->keyPressEvent(e);
00249 }
00250