499 lines
14 KiB
C++
499 lines
14 KiB
C++
/* 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
|
|
*/
|
|
// HotKeyConf.cpp
|
|
//
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
|
|
#include <SDL.h>
|
|
#include <QHeaderView>
|
|
#include <QCloseEvent>
|
|
#include <QMessageBox>
|
|
|
|
#include "Qt/main.h"
|
|
#include "Qt/dface.h"
|
|
#include "Qt/input.h"
|
|
#include "Qt/config.h"
|
|
#include "Qt/keyscan.h"
|
|
#include "Qt/fceuWrapper.h"
|
|
#include "Qt/HotKeyConf.h"
|
|
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfDialog_t::HotKeyConfDialog_t(QWidget *parent)
|
|
: QDialog(parent)
|
|
{
|
|
QVBoxLayout *mainLayout;
|
|
QHBoxLayout *hbox;
|
|
QPushButton *closeButton, *resetDefaults;
|
|
QTreeWidgetItem *item;
|
|
std::string prefix = "SDL.Hotkeys.";
|
|
const char *hkName, *hkKeySeq, *hkTitle, *hkGroup;
|
|
|
|
setWindowTitle("Hotkey Configuration");
|
|
|
|
resize(512, 512);
|
|
|
|
mainLayout = new QVBoxLayout();
|
|
|
|
tree = new HotKeyConfTree_t(this);
|
|
|
|
tree->setColumnCount(2);
|
|
tree->setSelectionMode( QAbstractItemView::SingleSelection );
|
|
tree->setAlternatingRowColors(true);
|
|
|
|
item = new QTreeWidgetItem();
|
|
item->setText(0, QString::fromStdString("Command"));
|
|
item->setText(1, QString::fromStdString("Key"));
|
|
item->setTextAlignment(0, Qt::AlignLeft);
|
|
item->setTextAlignment(1, Qt::AlignCenter);
|
|
|
|
tree->setHeaderItem(item);
|
|
|
|
tree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
|
|
|
for (int i = 0; i < HK_MAX; i++)
|
|
{
|
|
getHotKeyConfig( i, &hkName, &hkKeySeq, &hkTitle, &hkGroup );
|
|
|
|
tree->addGroup( hkGroup );
|
|
|
|
tree->addItem( hkGroup, i );
|
|
}
|
|
tree->finalize();
|
|
|
|
//connect( tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(hotKeyDoubleClicked(QTreeWidgetItem*,int) ) );
|
|
connect( tree, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(hotKeyActivated(QTreeWidgetItem*,int) ) );
|
|
|
|
mainLayout->addWidget(tree);
|
|
|
|
resetDefaults = new QPushButton( tr("Restore Defaults") );
|
|
resetDefaults->setIcon(style()->standardIcon(QStyle::SP_DialogResetButton));
|
|
connect(resetDefaults, SIGNAL(clicked(void)), this, SLOT(resetDefaultsCB(void)));
|
|
|
|
closeButton = new QPushButton( tr("Close") );
|
|
closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
|
|
connect(closeButton, SIGNAL(clicked(void)), this, SLOT(closeWindow(void)));
|
|
|
|
hbox = new QHBoxLayout();
|
|
hbox->addWidget( resetDefaults, 1 );
|
|
hbox->addStretch(5);
|
|
hbox->addWidget( closeButton, 1 );
|
|
mainLayout->addLayout( hbox );
|
|
|
|
setLayout(mainLayout);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfDialog_t::~HotKeyConfDialog_t(void)
|
|
{
|
|
//printf("Destroy Hot Key Config Window\n");
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfDialog_t::closeEvent(QCloseEvent *event)
|
|
{
|
|
//printf("Hot Key Close Window Event\n");
|
|
done(0);
|
|
deleteLater();
|
|
event->accept();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfDialog_t::closeWindow(void)
|
|
{
|
|
//printf("Close Window\n");
|
|
done(0);
|
|
deleteLater();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfTree_t::finalize(void)
|
|
{
|
|
QTreeWidgetItem *item;
|
|
std::map <std::string, QTreeWidgetItem*>::iterator it;
|
|
|
|
for (it=groupMap.begin(); it!=groupMap.end(); it++)
|
|
{
|
|
item = it->second;
|
|
|
|
addTopLevelItem(item);
|
|
|
|
item->setExpanded(true);
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
QTreeWidgetItem *HotKeyConfTree_t::addItem( const char *group, int hkIdx )
|
|
{
|
|
QTreeWidgetItem *itemGroup;
|
|
HotKeyConfTreeItem_t *item;
|
|
const char *hkName, *hkKeySeq, *hkTitle, *hkGroup;
|
|
|
|
itemGroup = findGroup(group);
|
|
|
|
if ( itemGroup == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
getHotKeyConfig( hkIdx, &hkName, &hkKeySeq, &hkTitle, &hkGroup );
|
|
|
|
item = new HotKeyConfTreeItem_t(hkIdx);
|
|
|
|
item->setText(0, tr(hkTitle));
|
|
item->setText(1, Hotkeys[hkIdx].getKeySeq().toString());
|
|
|
|
item->setTextAlignment(0, Qt::AlignLeft);
|
|
item->setTextAlignment(1, Qt::AlignCenter);
|
|
|
|
itemGroup->addChild(item);
|
|
return NULL;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
QTreeWidgetItem *HotKeyConfTree_t::addGroup( const char *group)
|
|
{
|
|
std::string s = group;
|
|
|
|
return addGroup(s);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
QTreeWidgetItem *HotKeyConfTree_t::addGroup(std::string group)
|
|
{
|
|
QTreeWidgetItem *item;
|
|
|
|
item = findGroup(group);
|
|
|
|
if ( item == NULL )
|
|
{
|
|
item = new QTreeWidgetItem( this, 0);
|
|
|
|
item->setText(0, QString::fromStdString(group));
|
|
|
|
groupMap[group] = item;
|
|
}
|
|
return item;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
QTreeWidgetItem *HotKeyConfTree_t::findGroup( const char *group)
|
|
{
|
|
std::string s = group;
|
|
|
|
return findGroup(s);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
QTreeWidgetItem *HotKeyConfTree_t::findGroup( std::string group)
|
|
{
|
|
std::map <std::string, QTreeWidgetItem*>::iterator it;
|
|
|
|
it = groupMap.find(group);
|
|
|
|
if ( it != groupMap.end() )
|
|
{
|
|
return it->second;
|
|
}
|
|
return NULL;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfTreeItem_t::HotKeyConfTreeItem_t(int idx, QTreeWidgetItem *parent)
|
|
: QTreeWidgetItem(parent,1)
|
|
{
|
|
hkIdx = idx;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfTreeItem_t::~HotKeyConfTreeItem_t(void)
|
|
{
|
|
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfDialog_t::resetDefaultsCB(void)
|
|
{
|
|
QTreeWidgetItem *groupItem;
|
|
HotKeyConfTreeItem_t *item;
|
|
std::string confName;
|
|
std::string prefix = "SDL.Hotkeys.";
|
|
const char *name, *keySeq;
|
|
|
|
for (int i=0; i<tree->topLevelItemCount(); i++)
|
|
{
|
|
groupItem = tree->topLevelItem(i);
|
|
|
|
for (int j=0; j<groupItem->childCount(); j++)
|
|
{
|
|
item = static_cast<HotKeyConfTreeItem_t*>(groupItem->child(j));
|
|
|
|
getHotKeyConfig( item->hkIdx, &name, &keySeq );
|
|
|
|
confName = prefix + name;
|
|
|
|
g_config->setOption( confName, keySeq );
|
|
|
|
item->setText(1, tr(keySeq));
|
|
}
|
|
}
|
|
setHotKeys();
|
|
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfDialog_t::keyPressEvent(QKeyEvent *event)
|
|
{
|
|
//printf("Hotkey Window Key Press: 0x%x \n", event->key() );
|
|
event->accept();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfDialog_t::keyReleaseEvent(QKeyEvent *event)
|
|
{
|
|
//printf("Hotkey Window Key Release: 0x%x \n", event->key() );
|
|
event->accept();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfDialog_t::hotKeyActivated(QTreeWidgetItem *item, int column)
|
|
{
|
|
HotKeyConfTreeItem_t *hkItem = static_cast<HotKeyConfTreeItem_t*>(item);
|
|
|
|
if ( hkItem->type() == 0 )
|
|
{
|
|
return;
|
|
}
|
|
HotKeyConfSetDialog_t *win = new HotKeyConfSetDialog_t( 1, hkItem, this );
|
|
|
|
win->exec();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfDialog_t::hotKeyDoubleClicked(QTreeWidgetItem *item, int column)
|
|
{
|
|
HotKeyConfTreeItem_t *hkItem = static_cast<HotKeyConfTreeItem_t*>(item);
|
|
|
|
if ( hkItem->type() == 0 )
|
|
{
|
|
return;
|
|
}
|
|
HotKeyConfSetDialog_t *win = new HotKeyConfSetDialog_t( 0, hkItem, this );
|
|
|
|
win->exec();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfTree_t::HotKeyConfTree_t(QWidget *parent)
|
|
: QTreeWidget(parent)
|
|
{
|
|
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfTree_t::~HotKeyConfTree_t(void)
|
|
{
|
|
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfTree_t::keyPressEvent(QKeyEvent *event)
|
|
{
|
|
QTreeWidget::keyPressEvent(event);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfTree_t::keyReleaseEvent(QKeyEvent *event)
|
|
{
|
|
QTreeWidget::keyReleaseEvent(event);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfSetDialog_t::HotKeyConfSetDialog_t( int discardNum, HotKeyConfTreeItem_t *itemIn, QWidget *parent )
|
|
: QDialog(parent)
|
|
{
|
|
QVBoxLayout *mainLayout;
|
|
QHBoxLayout *hbox;
|
|
QPushButton *clearButton, *okButton;
|
|
|
|
item = itemIn;
|
|
discardCount = discardNum;
|
|
|
|
setWindowTitle("Set Hot Key");
|
|
|
|
mainLayout = new QVBoxLayout();
|
|
hbox = new QHBoxLayout();
|
|
|
|
keySeqText = new QLineEdit();
|
|
keySeqText->setReadOnly(true);
|
|
keySeqText->setText( tr("Press a Key") );
|
|
|
|
mainLayout->addWidget(keySeqText);
|
|
|
|
mainLayout->addLayout( hbox );
|
|
|
|
clearButton = new QPushButton( tr("Clear") );
|
|
okButton = new QPushButton( tr("Ok") );
|
|
|
|
clearButton->setIcon(style()->standardIcon(QStyle::SP_DialogResetButton));
|
|
okButton->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton));
|
|
|
|
hbox->addWidget( clearButton );
|
|
hbox->addWidget( okButton );
|
|
|
|
setLayout( mainLayout );
|
|
|
|
connect( clearButton, SIGNAL(clicked(void)), this, SLOT(cleanButtonCB(void)) );
|
|
connect( okButton, SIGNAL(clicked(void)), this, SLOT( okButtonCB(void)) );
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
HotKeyConfSetDialog_t::~HotKeyConfSetDialog_t(void)
|
|
{
|
|
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::closeEvent(QCloseEvent *event)
|
|
{
|
|
//printf("Hot Key Close Window Event\n");
|
|
done(0);
|
|
deleteLater();
|
|
event->accept();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::closeWindow(void)
|
|
{
|
|
//printf("Close Window\n");
|
|
done(0);
|
|
deleteLater();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::keyPressEvent(QKeyEvent *event)
|
|
{
|
|
//printf("Hotkey Window Key Press: 0x%x \n", event->key() );
|
|
if ( discardCount == 0 )
|
|
{
|
|
assignHotkey(event);
|
|
}
|
|
else if ( discardCount > 0 )
|
|
{
|
|
discardCount--;
|
|
}
|
|
event->accept();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::keyReleaseEvent(QKeyEvent *event)
|
|
{
|
|
if ( discardCount == 0 )
|
|
{
|
|
assignHotkey(event);
|
|
}
|
|
else if ( discardCount > 0 )
|
|
{
|
|
discardCount--;
|
|
}
|
|
//printf("Hotkey Window Key Release: 0x%x \n", event->key() );
|
|
//assignHotkey(event);
|
|
event->accept();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::checkForConflicts(int hkIdx)
|
|
{
|
|
for (int i=0; i<HK_MAX; i++)
|
|
{
|
|
if ( hkIdx == i )
|
|
{
|
|
continue;
|
|
}
|
|
if ( Hotkeys[hkIdx].getKeySeq().matches( Hotkeys[i].getKeySeq() ) )
|
|
{
|
|
std::string msg;
|
|
const char *hkName1, *hkKeySeq1, *hkTitle1, *hkGroup1;
|
|
const char *hkName2, *hkKeySeq2, *hkTitle2, *hkGroup2;
|
|
|
|
getHotKeyConfig( i, &hkName1, &hkKeySeq1, &hkTitle1, &hkGroup1 );
|
|
getHotKeyConfig( hkIdx, &hkName2, &hkKeySeq2, &hkTitle2, &hkGroup2 );
|
|
|
|
msg.append(hkGroup2);
|
|
msg.append(" :: ");
|
|
msg.append(hkTitle2);
|
|
msg.append("\n\n");
|
|
msg.append("Conflicts with:\n\n");
|
|
msg.append(hkGroup1);
|
|
msg.append(" :: ");
|
|
msg.append(hkTitle1);
|
|
|
|
QMessageBox::warning( this,
|
|
tr("Hotkey Conflict Warning"), tr(msg.c_str()) );
|
|
//printf("Warning Key Conflict: %i and %i \n", hkIdx, i );
|
|
}
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::assignHotkey(QKeyEvent *event)
|
|
{
|
|
bool keyIsModifier;
|
|
//QKeySequence ks( event->modifiers() + event->key() );
|
|
QKeySequence ks( convKeyEvent2Sequence(event) );
|
|
SDL_Keycode k = convQtKey2SDLKeyCode((Qt::Key)event->key());
|
|
//SDL_Keymod m = convQtKey2SDLModifier(event->modifiers());
|
|
|
|
keyIsModifier = (k == SDLK_LCTRL) || (k == SDLK_RCTRL) ||
|
|
(k == SDLK_LSHIFT) || (k == SDLK_RSHIFT) ||
|
|
(k == SDLK_LALT) || (k == SDLK_RALT) ||
|
|
(k == SDLK_LGUI) || (k == SDLK_RGUI) ||
|
|
(k == SDLK_CAPSLOCK);
|
|
|
|
//printf("Assign: '%s' %i 0x%08x\n", ks.toString().toStdString().c_str(), event->key(), event->key() );
|
|
|
|
if ((k != SDLK_UNKNOWN) && !keyIsModifier)
|
|
{
|
|
std::string keyText;
|
|
std::string prefix = "SDL.Hotkeys.";
|
|
std::string confName;
|
|
|
|
confName = prefix + Hotkeys[item->hkIdx].getConfigName();
|
|
|
|
keyText = ks.toString().toStdString();
|
|
|
|
g_config->setOption( confName, keyText);
|
|
|
|
setHotKeys();
|
|
|
|
checkForConflicts(item->hkIdx);
|
|
|
|
if ( item )
|
|
{
|
|
item->setText(1, QString::fromStdString(keyText));
|
|
}
|
|
|
|
done(0);
|
|
deleteLater();
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::cleanButtonCB(void)
|
|
{
|
|
std::string prefix = "SDL.Hotkeys.";
|
|
std::string confName;
|
|
|
|
confName = prefix + Hotkeys[item->hkIdx].getConfigName();
|
|
|
|
g_config->setOption( confName, "");
|
|
|
|
setHotKeys();
|
|
|
|
if ( item )
|
|
{
|
|
item->setText(1, tr(""));
|
|
}
|
|
|
|
done(0);
|
|
deleteLater();
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void HotKeyConfSetDialog_t::okButtonCB(void)
|
|
{
|
|
done(0);
|
|
deleteLater();
|
|
}
|
|
//----------------------------------------------------------------------------
|