PDA

View Full Version : Keyboard widget producing incorrect value



Vysero
6th September 2018, 22:21
The keyboard widget is casting 16 bit hex value into an 8 bit char, losing the leading byte. The character that appears on the '5' button is currently a 'G' (0x0047). It should actually be a '?' (Capital N with caron - 0x0147):



// Create keyboard
//
// Note: The hex numbers here are unicode code points, not
// extended ascii or utf-8 encoding.
//
QHBoxLayout* row1 = new QHBoxLayout();
createBtn(row1, 2, '1', '_', '1', '!', static_cast<char>(0xBC));
createBtn(row1, 2, '2', '%', '2', '@', static_cast<char>(0xBD));
createBtn(row1, 2, '3', '&', '3', '?', static_cast<char>(0xBE));
createBtn(row1, 2, '4', '(', '4', static_cast<char>(0xFF), static_cast<char>(0xB0));
createBtn(row1, 2, '5', ')', '5', static_cast<char>(0xDF), static_cast<char>(0x0147));
createBtn(row1, 2, '6', '-', '6', static_cast<char>(0xE0), static_cast<char>(0xC0));
createBtn(row1, 2, '7', ':', '7', static_cast<char>(0xE1), static_cast<char>(0xC1));
createBtn(row1, 2, '8', '/', '8', static_cast<char>(0xE2), static_cast<char>(0xC2));
createBtn(row1, 2, '9', ',', '9', static_cast<char>(0xE3), static_cast<char>(0xC3));
createBtn(row1, 2, '0', '.', '0', static_cast<char>(0xE4), static_cast<char>(0xC4));
createBtn(row1, 3, false, Qt::Key_Backspace, "<---");

Has anyone ran into something similar?

Ginsengelf
7th September 2018, 07:19
Hi, 0x0147 is too large to fit into a char (which has only 8 bit), so you get the truncated value.

Ginsengelf

d_stranz
7th September 2018, 19:46
Not only that, but it is a signed char which means any value over 0x7F will be negative. createBtn() might ignore the sign, but as Ginsengelf says, 0x0147 is still too large for a char.

I do not know the signature for the createBtn() method, but if the last two arguments are actually QChar, then changing the static cast type to ushort will work.

Vysero
7th September 2018, 20:28
QString KeyboardWidget::c2s(char value) const
{
// Correct for automatic mnemonics.
if (value=='&') return QLatin1String("&&");
else return QString(static_cast<QChar>(QLatin1Char(value)));
}


int KeyboardWidget::createBtn(QHBoxLayout* row,
int span,
char normal,
char shift,
char caps,
char alt,
char capAlt,
bool autoRepeat)
{
int id = m_allButtons.count();
KeyboardWidgetButton* btn = new KeyboardWidgetButton(this,
id,
c2s(normal),
c2s(shift),
c2s(caps),
c2s(alt),
c2s(capAlt));
row->addWidget(btn, span);
btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn->setAutoRepeat(autoRepeat);
VERIFY(connect(btn, SIGNAL(takeAction(int)),
this, SLOT(buttonClicked(int))));
m_allButtons.append(btn);
return id;
}

If you were wondering.

d_stranz
8th September 2018, 04:39
Well, then you are stuck with 8-bit signed chars as the keycodes. What is "c2s()" - "char to short"? If that's the case and you have this source code, change createBtn() to take ushort instead of char arguments, and pass these values directly into the KeyboardWidgetButton() constructor (without passing them through the c2s() conversion). You will then have buttons that return 16-bit keycodes.

Vysero
12th September 2018, 16:19
Not sure if this is what you mean:


QHBoxLayout* row2 = new QHBoxLayout();
createBtn(row2, 1, 'q', 'Q', 'Q', 0xE5, 0xC5);
createBtn(row2, 1, 'w', 'W', 'W', 0xE6, 0xC6);
createBtn(row2, 1, 'e', 'E', 'E', 0xE7, 0xC7);
createBtn(row2, 1, 'r', 'R', 'R', 0xE8, 0xC8);
createBtn(row2, 1, 't', 'T', 'T', 0xE9, 0xC9);
createBtn(row2, 1, 'y', 'Y', 'Y', 0xEA, 0xCA);
createBtn(row2, 1, 'u', 'U', 'U', 0xEB, 0xCB);
createBtn(row2, 1, 'i', 'I', 'I', 0xEC, 0xCC);
createBtn(row2, 1, 'o', 'O', 'O', 0xED, 0xCD);
createBtn(row2, 1, 'p', 'P', 'P', 0xEE, 0xCE);

QString KeyboardWidget::c2s(char value) const
{
// Correct for automatic mnemonics.
if (value=='&') return QLatin1String("&&");
else return QString(static_cast<QChar>(QLatin1Char(value)));
}


int KeyboardWidget::createBtn(QHBoxLayout* row,
int span,
ushort normal,
ushort shift,
ushort caps,
ushort alt,
ushort capAlt,
bool autoRepeat)
{
int id = m_allButtons.count();
KeyboardWidgetButton* btn = new KeyboardWidgetButton(this,
id,
normal,
shift,
caps,
alt,
capAlt);
row->addWidget(btn, span);
btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn->setAutoRepeat(autoRepeat);
VERIFY(connect(btn, SIGNAL(takeAction(int)),
this, SLOT(buttonClicked(int))));
m_allButtons.append(btn);
return id;
}


int KeyboardWidget::createBtn(QHBoxLayout* row,
int span,
bool checkable,
int key,
const char* text,
bool autoRepeat)
{
int id = m_allButtons.count();
KeyboardWidgetButton* btn = new KeyboardWidgetButton(this, id, key, QLatin1String(text));
row->addWidget(btn, span);
btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn->setCheckable(checkable);
btn->setAutoRepeat(autoRepeat);
VERIFY(connect(btn, SIGNAL(takeAction(int)),
this, SLOT(buttonClicked(int))));
m_allButtons.append(btn);
return id;
}

but compilation gives:


: In member function 'int KeyboardWidget::createBtn(QHBoxLayout*, int, ushort, ushort, ushort, ushort, ushort, bool)':
: error: 'QString::QString(const char*)' is private
KeyboardWidget.cpp:329: error: within this context
KeyboardWidget.cpp:329: error: invalid conversion from 'ushort' to 'const char*'
KeyboardWidget.cpp:329: error: initializing argument 1 of 'QString::QString(const char*)'

Vysero
13th September 2018, 17:18
Okay, I got it working.