Virtual family keyboard in work for Qt GUI.

This commit is contained in:
mjbudd77 2022-03-05 15:18:30 -05:00
parent 8ad5767a3b
commit 7d3f0690e6
7 changed files with 557 additions and 2 deletions

View File

@ -506,6 +506,7 @@ set(SRC_DRIVERS_SDL
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerSDL.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/InputConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FamilyKeyboard.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TimingConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FrameTimingStats.cpp

View File

@ -0,0 +1,372 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020 mjbudd77
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// FamilyKeyboard.cpp
#include <QPainter>
#include <QFontMetrics>
#include "Qt/config.h"
#include "Qt/fceuWrapper.h"
#include "Qt/FamilyKeyboard.h"
static const char *keyNames[] =
{
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
"-",
"^",
"\\",
"STP",
"ESC",
"Q",
"W",
"E",
"R",
"T",
"Y",
"U",
"I",
"O",
"P",
"@",
"[",
"RETURN",
"CTR",
"A",
"S",
"D",
"F",
"G",
"H",
"J",
"K",
"L",
";",
":",
"]",
"KANA",
"SHIFT",
"Z",
"X",
"C",
"V",
"B",
"N",
"M",
",",
".",
"/",
"_",
"SHIFT",
"GRPH",
"SPACE",
"CLR",
"INS",
"DEL",
"UP",
"LEFT",
"RIGHT",
"DOWN",
NULL
};
//*********************************************************************************
FamilyKeyboardWidget::FamilyKeyboardWidget( QWidget *parent )
{
QFont font;
std::string fontString;
g_config->getOption("SDL.FamilyKeyboardFont", &fontString);
if ( fontString.size() > 0 )
{
font.fromString( QString::fromStdString( fontString ) );
}
else
{
font.setFamily("Courier New");
font.setStyle( QFont::StyleNormal );
font.setStyleHint( QFont::Monospace );
}
setFont( font );
setMinimumSize( 512, 256 );
calcFontData();
}
//*********************************************************************************
FamilyKeyboardWidget::~FamilyKeyboardWidget(void)
{
}
//*********************************************************************************
void FamilyKeyboardWidget::calcFontData(void)
{
QWidget::setFont(font());
QFontMetrics metrics(font());
#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
pxCharWidth = metrics.horizontalAdvance(QLatin1Char('2'));
#else
pxCharWidth = metrics.width(QLatin1Char('2'));
#endif
pxCharHeight = metrics.capHeight();
//pxLineSpacing = metrics.lineSpacing() * 1.25;
//pxCursorHeight = metrics.height();
pxBtnGridX = (3 * pxCharWidth) + 2;
pxBtnGridY = (2 * pxCharHeight);
if ( pxBtnGridX % 2 )
{
pxBtnGridX++;
}
if ( pxBtnGridY % 2 )
{
pxBtnGridY++;
}
setMinimumWidth( pxBtnGridX * 25 );
setMinimumHeight( pxBtnGridY * 8 );
}
//*********************************************************************************
void FamilyKeyboardWidget::paintEvent(QPaintEvent *event)
{
int i, j, x, y, w, h, xs, ys;
QPainter painter(this);
// Row 1
x = pxBtnGridX / 2;
y = pxBtnGridY / 2;
w = pxBtnGridX * 2;
h = pxBtnGridY;
xs = w / 4;
ys = h / 4;
for (i=0; i<8; i++)
{
j = i;
key[j].rect = QRect( x, y, w, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += (w + xs);
}
// Row 2
x = pxBtnGridX;
y += pxBtnGridY + ys;
w = pxBtnGridX;
xs = w / 4;
for (i=8; i<22; i++)
{
j = i;
key[j].rect = QRect( x, y, w, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += (w + xs);
}
// Row 3
x = pxBtnGridX / 2;
y += pxBtnGridY + ys;
w = pxBtnGridX;
xs = w / 4;
for (i=22; i<35; i++)
{
j = i;
key[j].rect = QRect( x, y, w, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += (w + xs);
}
x += (xs);
j = 35;
key[j].rect = QRect( x, y, w*3, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
// Row 4
x = pxBtnGridX;
y += pxBtnGridY + ys;
w = pxBtnGridX;
xs = w / 4;
x -= xs;
for (i=36; i<49; i++)
{
j = i;
key[j].rect = QRect( x, y, w, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += (w + xs);
}
j = 49;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
// Row 5
x = pxBtnGridX / 2;
y += pxBtnGridY + ys;
w = pxBtnGridX;
xs = w / 4;
//x -= xs;
j = 50;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += ((w*2) + xs);
for (i=51; i<62; i++)
{
j = i;
key[j].rect = QRect( x, y, w, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += (w + xs);
}
j = 62;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
// Row 6
x = (pxBtnGridX * 5) / 2;
y += pxBtnGridY + ys;
w = pxBtnGridX;
xs = w / 4;
x += (2*xs);
j = 63;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += ((w*2) + xs);
j = 64;
key[j].rect = QRect( x, y, (w*8) + (xs*7), h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
// Row 7
xs = pxBtnGridX / 4;
x = (pxBtnGridX+xs) * 17;
y = (pxBtnGridY * 3) / 2;
w = pxBtnGridX;
xs = w / 4;
//x += (2*xs);
y += (2*ys);
for (i=65; i<68; i++)
{
j = i;
key[j].rect = QRect( x, y, w, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += (w + xs);
}
// Arrow Keys
x = (pxBtnGridX+xs) * 17 + (pxBtnGridX)/2 + xs;
y += pxBtnGridY + ys;
j = 68;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x = (pxBtnGridX+xs) * 17 - (pxBtnGridX)/2 + (xs/2);
y += pxBtnGridY + ys;
j = 69;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x += ((w*2) + xs);
j = 70;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
x = (pxBtnGridX+xs) * 17 + (pxBtnGridX)/2 + xs;
y += pxBtnGridY + ys;
j = 71;
key[j].rect = QRect( x, y, w*2, h );
painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) );
painter.drawRect( key[j].rect );
}
//*********************************************************************************

View File

@ -0,0 +1,37 @@
#include <QRect>
#include <QWidget>
#include <QFont>
class FKB_Key_t
{
public:
QRect rect;
char name[16];
};
class FamilyKeyboardWidget : public QWidget
{
Q_OBJECT
public:
FamilyKeyboardWidget( QWidget *parent = 0);
~FamilyKeyboardWidget(void);
static const unsigned int NUM_KEYS = 0x48;
protected:
//void keyPressEvent(QKeyEvent *event);
//void kepaintEvent(QPaintEvent *event);
void paintEvent(QPaintEvent *event);
void calcFontData(void);
int pxCharWidth;
int pxCharHeight;
int pxBtnGridX;
int pxBtnGridY;
FKB_Key_t key[NUM_KEYS];
};

View File

@ -38,9 +38,12 @@
#include "Qt/fceuWrapper.h"
#include "Qt/ConsoleWindow.h"
#include "Qt/ConsoleUtilities.h"
#include "Qt/FamilyKeyboard.h"
#include "Qt/InputConf.h"
static InputConfDialog_t *win = NULL;
static FKBConfigDialog *fkbCfgWin = NULL;
//----------------------------------------------------------------------------
void openInputConfWindow(QWidget *parent)
{
@ -244,6 +247,7 @@ InputConfDialog_t::InputConfDialog_t(QWidget *parent)
connect(nesPortConfButton[0], SIGNAL(clicked(void)), this, SLOT(port1Configure(void)));
connect(nesPortConfButton[1], SIGNAL(clicked(void)), this, SLOT(port2Configure(void)));
connect(expPortConfButton , SIGNAL(clicked(void)), this, SLOT(expPortConfigure(void)));
connect(loadConfigButton, SIGNAL(clicked(void)), this, SLOT(openLoadPresetFile(void)));
connect(saveConfigButton, SIGNAL(clicked(void)), this, SLOT(openSavePresetFile(void)));
@ -329,6 +333,8 @@ void InputConfDialog_t::updatePortLabels(void)
expPortLabel->setText(expPortComboxBox->itemText(j));
}
}
expPortConfButton->setEnabled( curNesInput[2] == SIFC_FKB );
}
//----------------------------------------------------------------------------
void InputConfDialog_t::updatePortComboBoxes(void)
@ -428,6 +434,18 @@ void InputConfDialog_t::port2Configure(void)
openPortConfig(1);
}
//----------------------------------------------------------------------------
void InputConfDialog_t::expPortConfigure(void)
{
if ( curNesInput[2] == SIFC_FKB )
{
if ( fkbCfgWin == NULL )
{
fkbCfgWin = new FKBConfigDialog(this);
fkbCfgWin->show();
}
}
}
//----------------------------------------------------------------------------
void InputConfDialog_t::openLoadPresetFile(void)
{
int ret, useNativeFileDialogVal;
@ -587,3 +605,109 @@ void InputConfDialog_t::updatePeriodic(void)
}
}
//----------------------------------------------------------------------------
//--- Family Keyboard Config Dialog
//----------------------------------------------------------------------------
FKBConfigDialog::FKBConfigDialog(QWidget *parent)
: QDialog(parent)
{
QVBoxLayout *mainVbox;
QHBoxLayout *hbox;
QPushButton *closeButton;
QTreeWidgetItem *item;
setWindowTitle( "Family Keyboard Config" );
mainVbox = new QVBoxLayout();
mainVbox->addWidget( new FamilyKeyboardWidget() );
setLayout( mainVbox );
keyTree = new QTreeWidget();
keyTree->setColumnCount(2);
keyTree->setSelectionMode( QAbstractItemView::SingleSelection );
keyTree->setAlternatingRowColors(true);
item = new QTreeWidgetItem();
item->setText(0, QString::fromStdString("FKB Key"));
item->setText(1, QString::fromStdString("SDL Binding"));
item->setTextAlignment(0, Qt::AlignLeft);
item->setTextAlignment(1, Qt::AlignCenter);
keyTree->setHeaderItem(item);
keyTree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
for (int i=0; i<FAMILYKEYBOARD_NUM_BUTTONS; i++)
{
item = new QTreeWidgetItem();
item->setText(0, tr(FamilyKeyBoardNames[i]));
//item->setText(1, tr(FamilyKeyBoardNames[i]));
item->setTextAlignment(0, Qt::AlignLeft);
item->setTextAlignment(1, Qt::AlignCenter);
keyTree->addTopLevelItem(item);
}
updateBindingList();
mainVbox->addWidget( keyTree );
hbox = new QHBoxLayout();
mainVbox->addLayout( hbox );
closeButton = new QPushButton( tr("Close") );
closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
hbox->addStretch(5);
hbox->addWidget( closeButton, 1);
connect(closeButton , SIGNAL(clicked(void)), this, SLOT(closeWindow(void)));
}
//----------------------------------------------------------------------------
FKBConfigDialog::~FKBConfigDialog(void)
{
}
//----------------------------------------------------------------------------
void FKBConfigDialog::updateBindingList(void)
{
char keyNameStr[128];
for (int i=0; i<FAMILYKEYBOARD_NUM_BUTTONS; i++)
{
QTreeWidgetItem *item = keyTree->topLevelItem(i);
item->setText(0, tr(FamilyKeyBoardNames[i]));
if (fkbmap[i].ButtType == BUTTC_KEYBOARD)
{
snprintf(keyNameStr, sizeof(keyNameStr), "%s",
SDL_GetKeyName(fkbmap[i].ButtonNum));
}
else
{
strcpy(keyNameStr, ButtonName(&fkbmap[i]));
}
item->setText(1, tr(keyNameStr));
}
}
//----------------------------------------------------------------------------
void FKBConfigDialog::closeEvent(QCloseEvent *event)
{
printf("FKB Config Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------------------------------
void FKBConfigDialog::closeWindow(void)
{
//printf("Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------------------------------

View File

@ -20,6 +20,25 @@
#include "Qt/main.h"
class FKBConfigDialog : public QDialog
{
Q_OBJECT
public:
FKBConfigDialog(QWidget *parent = 0);
~FKBConfigDialog(void);
protected:
void closeEvent(QCloseEvent *event);
void updateBindingList(void);
QTreeWidget *keyTree;
public slots:
void closeWindow(void);
};
class InputConfDialog_t : public QDialog
{
Q_OBJECT
@ -58,6 +77,7 @@ public slots:
private slots:
void port1Configure(void);
void port2Configure(void);
void expPortConfigure(void);
void port1Select(int index);
void port2Select(int index);
void expSelect(int index);

View File

@ -1841,7 +1841,7 @@ void InitInputInterface()
FCEUI_SetInputFourscore((eoptions & EO_FOURSCORE) != 0);
}
static ButtConfig fkbmap[0x48] = {
ButtConfig fkbmap[FAMILYKEYBOARD_NUM_BUTTONS] = {
/* 0 */ MK(SDLK_F1), MK(SDLK_F2), MK(SDLK_F3), MK(SDLK_F4), MK(SDLK_F5), MK(SDLK_F6), MK(SDLK_F7), MK(SDLK_F8),
/* 8 */ MK(SDLK_1), MK(SDLK_2), MK(SDLK_3), MK(SDLK_4), MK(SDLK_5), MK(SDLK_6), MK(SDLK_7), MK(SDLK_8), MK(SDLK_9),
/* 17 */ MK(SDLK_0),
@ -1870,7 +1870,7 @@ static void UpdateFKB()
leftShiftDown = DTestButton(&fkbmap[50]);
for (x = 0; x < 0x48; x++)
for (x = 0; x < FAMILYKEYBOARD_NUM_BUTTONS; x++)
{
if ( leftShiftDown && (x == 62) )
{ // Family BASIC appears to not like when both shift keys are pressed at the

View File

@ -129,6 +129,7 @@ extern bool replaceP2StartWithMicrophone;
//extern ButtConfig powerpadsc[2][12];
//extern ButtConfig QuizKingButtons[6];
//extern ButtConfig FTrainerButtons[12];
extern ButtConfig fkbmap[FAMILYKEYBOARD_NUM_BUTTONS];
void IncreaseEmulationSpeed(void);
void DecreaseEmulationSpeed(void);