mirror of
https://github.com/mupen64plus/mupen64plus-oldsvn.git
synced 2025-04-02 10:52:35 -04:00
476 lines
14 KiB
C++
476 lines
14 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Mupen64plus - mainwindow.cpp *
|
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
|
* Copyright (C) 2008 Slougi *
|
|
* *
|
|
* 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. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include <QtGui>
|
|
|
|
#include "mainwindow.h"
|
|
#include "mainwidget.h"
|
|
#include "globals.h"
|
|
#include "rommodel.h"
|
|
|
|
#include "settingsdialog.h"
|
|
|
|
namespace core {
|
|
extern "C" {
|
|
#include "../gui.h"
|
|
#include "../main.h"
|
|
#include "../plugin.h"
|
|
#include "../savestates.h"
|
|
#include "../rom.h"
|
|
#include "../config.h"
|
|
}
|
|
}
|
|
|
|
MainWindow::MainWindow()
|
|
: QMainWindow(0)
|
|
, m_statusBarLabel(0)
|
|
, m_uiActions(0)
|
|
{
|
|
setupUi(this);
|
|
setupActions();
|
|
setState(core::GUI_STATE_STOPPED);
|
|
m_statusBarLabel = new QLabel;
|
|
statusBar()->addPermanentWidget(m_statusBarLabel);
|
|
|
|
connect(mainWidget, SIGNAL(itemCountChanged(int)),
|
|
this, SLOT(itemCountUpdate(int)));
|
|
connect(mainWidget, SIGNAL(romDoubleClicked(QString, unsigned int)),
|
|
this, SLOT(romOpen(QString, unsigned int)));
|
|
|
|
QSize size(core::config_get_number("MainWindowWidth",600),
|
|
core::config_get_number("MainWindowHeight",400));
|
|
QPoint position(core::config_get_number("MainWindowXPosition",0),
|
|
core::config_get_number("MainWindowYPosition",0));
|
|
|
|
QDesktopWidget *d = QApplication::desktop();
|
|
QSize desktop = d->size();
|
|
|
|
if (position.x() > desktop.width()) {
|
|
position.setX(0);
|
|
}
|
|
if (position.y() > desktop.height()) {
|
|
position.setY(0);
|
|
}
|
|
|
|
if (size.width() > desktop.width()) {
|
|
size.setWidth(600);
|
|
}
|
|
if (size.height() > desktop.height()) {
|
|
size.setHeight(400);
|
|
}
|
|
|
|
if ((position.x() + size.width()) > desktop.width()) {
|
|
position.setX(desktop.width() - size.width());
|
|
}
|
|
if ((position.y()+size.height())>desktop.height()) {
|
|
position.setY(desktop.height() - size.height());
|
|
}
|
|
|
|
resize(size);
|
|
move(position);
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
#ifdef __WIN32__
|
|
delete m_renderWindow;
|
|
m_renderWindow = 0;
|
|
#endif
|
|
}
|
|
|
|
void MainWindow::closeEvent(QCloseEvent *event)
|
|
{
|
|
Q_UNUSED(event);
|
|
core::config_put_number("MainWindowWidth", width());
|
|
core::config_put_number("MainWindowHeight", height());
|
|
core::config_put_number("MainWindowXPosition", x());
|
|
core::config_put_number("MainWindowYPosition", y());
|
|
core::config_put_bool("StatusBarVisible", actionShowStatusbar->isChecked());
|
|
core::config_put_bool("ToolBarVisible", actionShowToolbar->isChecked());
|
|
core::config_put_bool("FilterVisible", actionShowFilter->isChecked());
|
|
#ifdef __WIN32__
|
|
if (m_renderWindow) {
|
|
m_renderWindow->close();
|
|
m_renderWindow->deleteLater();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef __WIN32__
|
|
|
|
bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
|
|
{
|
|
if (obj == m_renderWindow) {
|
|
switch (ev->type()) {
|
|
case QEvent::Close:
|
|
emulationStop();
|
|
return false;
|
|
break;
|
|
case QEvent::MouseButtonDblClick:
|
|
actionFullScreen->toggle();
|
|
return true;
|
|
break;
|
|
case QEvent::KeyRelease:
|
|
{
|
|
QKeyEvent* qke = static_cast<QKeyEvent*>(ev);
|
|
foreach (QObject* child, children()) {
|
|
if (QAction*a = qobject_cast<QAction*>(child)) {
|
|
QKeySequence seq(qke->key() + qke->modifiers());
|
|
if (seq == a->shortcut()) {
|
|
a->activate(QAction::Trigger);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
} else {
|
|
return QMainWindow::eventFilter(obj, ev);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void MainWindow::showInfoMessage(const QString& msg)
|
|
{
|
|
statusBar()->showMessage(msg);
|
|
}
|
|
|
|
void MainWindow::showAlertMessage(const QString& msg)
|
|
{
|
|
QMessageBox::critical(this, "Alert", msg);
|
|
}
|
|
|
|
bool MainWindow::confirmMessage(const QString& msg)
|
|
{
|
|
QMessageBox::StandardButton res;
|
|
res = QMessageBox::question(this,
|
|
tr("Confirm"),
|
|
msg,
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
switch (res) {
|
|
case QMessageBox::Yes:
|
|
return true;
|
|
break;
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MainWindow::romOpen()
|
|
{
|
|
QString filter = RomExtensions.join(" ");
|
|
QString filename = QFileDialog::getOpenFileName(this,
|
|
tr("Select Rom"),
|
|
QString(),
|
|
filter);
|
|
if (!filename.isEmpty()) {
|
|
romOpen(filename, 0);
|
|
}
|
|
}
|
|
|
|
void MainWindow::romOpen(const QString& url)
|
|
{
|
|
romOpen(url, 0);
|
|
}
|
|
|
|
void MainWindow::romOpen(const QString& url, unsigned int archivefile)
|
|
{
|
|
if (core::open_rom(url.toLocal8Bit(), archivefile) == 0) {
|
|
startEmulation();
|
|
}
|
|
}
|
|
|
|
void MainWindow::romClose()
|
|
{
|
|
core::close_rom();
|
|
}
|
|
|
|
void MainWindow::emulationStart()
|
|
{
|
|
if(!core::rom) {
|
|
QModelIndex index = mainWidget->getRomBrowserIndex();
|
|
QString filename = index.data(RomModel::FullPath).toString();
|
|
unsigned int archivefile = index.data(RomModel::ArchiveFile).toUInt();
|
|
if (filename.isEmpty()) {
|
|
if (confirmMessage(tr("There is no Rom loaded." \
|
|
" Do you want to load one?"))) {
|
|
romOpen();
|
|
}
|
|
return;
|
|
} else {
|
|
romOpen(filename, archivefile);
|
|
}
|
|
}
|
|
else
|
|
startEmulation();
|
|
}
|
|
|
|
void MainWindow::emulationPauseContinue()
|
|
{
|
|
core::pauseContinueEmulation();
|
|
}
|
|
|
|
void MainWindow::emulationStop()
|
|
{
|
|
core::stopEmulation();
|
|
#ifdef __WIN32__
|
|
if (m_renderWindow) {
|
|
m_renderWindow->close();
|
|
m_renderWindow->deleteLater();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void MainWindow::fullScreenToggle()
|
|
{
|
|
if(core::g_EmulatorRunning)
|
|
core::changeWindow();
|
|
}
|
|
|
|
void MainWindow::saveStateSave()
|
|
{
|
|
if (core::g_EmulatorRunning) {
|
|
core::savestates_job |= SAVESTATE;
|
|
}
|
|
}
|
|
|
|
void MainWindow::saveStateSaveAs()
|
|
{
|
|
if (core::g_EmulatorRunning) {
|
|
QString filename = QFileDialog::getSaveFileName(this);
|
|
if (!filename.isEmpty()) {
|
|
core::savestates_select_filename(filename.toLocal8Bit());
|
|
core::savestates_job |= SAVESTATE;
|
|
}
|
|
} else {
|
|
showAlertMessage(tr("Emulation not running!"));
|
|
}
|
|
}
|
|
|
|
void MainWindow::saveStateLoad()
|
|
{
|
|
if (core::g_EmulatorRunning) {
|
|
core::savestates_job |= LOADSTATE;
|
|
}
|
|
}
|
|
|
|
void MainWindow::saveStateLoadFrom()
|
|
{
|
|
if (core::g_EmulatorRunning) {
|
|
QString filename = QFileDialog::getOpenFileName(this);
|
|
if (!filename.isEmpty()) {
|
|
core::savestates_select_filename(filename.toLocal8Bit());
|
|
core::savestates_job |= LOADSTATE;
|
|
}
|
|
} else {
|
|
showAlertMessage(tr("Emulation not running!"));
|
|
}
|
|
}
|
|
|
|
void MainWindow::savestateCheckSlot()
|
|
{
|
|
int slot = core::savestates_get_slot();
|
|
|
|
foreach(QAction* a, slotActions) {
|
|
a->setChecked(false);
|
|
}
|
|
|
|
if (slot >= 0 && slot < slotActions.count()) {
|
|
QAction* a = slotActions.at(slot);
|
|
a->setChecked(true);
|
|
}
|
|
}
|
|
|
|
void MainWindow::savestateSelectSlot(QAction* a)
|
|
{
|
|
bool ok = false;
|
|
int slot = a->data().toInt(&ok);
|
|
if (ok) {
|
|
core::savestates_select_slot(slot);
|
|
}
|
|
}
|
|
|
|
//Slot should be renamed.
|
|
void MainWindow::configDialogShow()
|
|
{
|
|
SettingsDialog* d = new SettingsDialog(this);
|
|
d->exec();
|
|
}
|
|
|
|
void MainWindow::itemCountUpdate(int count)
|
|
{
|
|
m_statusBarLabel->setText(tr("%n rom(s)", "", count));
|
|
}
|
|
|
|
void MainWindow::aboutDialogShow()
|
|
{
|
|
QMessageBox::about(this,
|
|
tr("About Mupen64Plus"),
|
|
tr("<html><b>Mupen64Plus N64 Emulator</b><br/>\
|
|
<a href=\"http://code.google.com/p/mupen64plus/\">Home...</a>\
|
|
</html>"));
|
|
}
|
|
|
|
void MainWindow::customEvent(QEvent* event)
|
|
{
|
|
switch (event->type()) {
|
|
case InfoEventType:
|
|
showInfoMessage(static_cast<InfoEvent*>(event)->message);
|
|
break;
|
|
case AlertEventType:
|
|
showAlertMessage(static_cast<AlertEvent*>(event)->message);
|
|
break;
|
|
default:
|
|
qDebug("Got unknown custom event of type %d!", event->type());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MainWindow::startEmulation()
|
|
{
|
|
#ifdef __WIN32__
|
|
m_renderWindow = new QWidget;
|
|
m_renderWindow->addActions(actions());
|
|
m_renderWindow->installEventFilter(this);
|
|
m_renderWindow->show();
|
|
core::g_RenderWindow = reinterpret_cast<core::HWND__*>(m_renderWindow->winId());
|
|
core::g_StatusBar = reinterpret_cast<core::HWND__*>(statusBar()->winId());
|
|
#endif
|
|
|
|
core::startEmulation();
|
|
}
|
|
|
|
void MainWindow::setupActions()
|
|
{
|
|
//File Actions
|
|
actionOpenRom->setIcon(icon("mupen64cart.png"));
|
|
connect(actionOpenRom, SIGNAL(triggered()), this, SLOT(romOpen()));
|
|
actionCloseRom->setIcon(icon("edit-delete.png"));
|
|
connect(actionCloseRom, SIGNAL(triggered()), this, SLOT(romClose()));
|
|
actionQuit->setIcon(icon("dialog-error.png"));
|
|
connect(actionQuit, SIGNAL(triggered()), this, SLOT(close()));
|
|
|
|
//Emulation Actions
|
|
actionStart->setIcon(icon("media-playback-start.png"));
|
|
connect(actionStart, SIGNAL(triggered()), this, SLOT(emulationStart()));
|
|
actionPause->setIcon(icon("media-playback-pause.png"));
|
|
connect(actionPause, SIGNAL(triggered()),
|
|
this, SLOT(emulationPauseContinue()));
|
|
actionStop->setIcon(icon("media-playback-stop.png"));
|
|
connect(actionStop, SIGNAL(triggered()), this, SLOT(emulationStop()));
|
|
actionSaveState->setIcon(icon("document-save.png"));
|
|
connect(actionSaveState, SIGNAL(triggered()),
|
|
this, SLOT(saveStateSave()));
|
|
actionLoadState->setIcon(icon("document-revert.png"));
|
|
connect(actionLoadState, SIGNAL(triggered()), this, SLOT(saveStateLoad()));
|
|
actionSaveStateAs->setIcon(icon("document-save-as.png"));
|
|
connect(actionSaveStateAs, SIGNAL(triggered()),
|
|
this, SLOT(saveStateSaveAs()));
|
|
actionLoadStateFrom->setIcon(icon("document-open.png"));
|
|
connect(actionLoadStateFrom, SIGNAL(triggered()),
|
|
this, SLOT(saveStateLoadFrom()));
|
|
|
|
actionCurrentSaveStateSlot->setIcon(icon("star.png"));
|
|
|
|
QMenu* slotMenu = new QMenu(this);
|
|
QActionGroup* slotActionGroup = new QActionGroup(actionCurrentSaveStateSlot);
|
|
for(int i = 0; i < 10; i++) {
|
|
QAction* slot = slotMenu->addAction(tr("Slot &%1").arg(i));
|
|
slot->setShortcut(QString("Ctrl+%1").arg(i));
|
|
slot->setCheckable(true);
|
|
slot->setData(i);
|
|
slotActionGroup->addAction(slot);
|
|
slotActions << slot;
|
|
}
|
|
actionCurrentSaveStateSlot->setMenu(slotMenu);
|
|
connect(slotMenu, SIGNAL(aboutToShow()), this, SLOT(savestateCheckSlot()));
|
|
connect(slotActionGroup, SIGNAL(triggered(QAction*)),
|
|
this, SLOT(savestateSelectSlot(QAction*)));
|
|
|
|
if (QWidget* w = toolBar->widgetForAction(actionCurrentSaveStateSlot)) {
|
|
if (QToolButton* tb = qobject_cast<QToolButton*>(w)) {
|
|
tb->setPopupMode(QToolButton::InstantPopup);
|
|
}
|
|
}
|
|
|
|
//Settings Actions
|
|
connect(actionShowFilter, SIGNAL(toggled(bool)),
|
|
mainWidget, SLOT(showFilter(bool)));
|
|
actionFullScreen->setIcon(icon("view-fullscreen.png"));
|
|
connect(actionFullScreen, SIGNAL(triggered()),
|
|
this, SLOT(fullScreenToggle()));
|
|
actionConfigureMupen64Plus->setIcon(icon("preferences-system.png"));
|
|
connect(actionConfigureMupen64Plus, SIGNAL(triggered()),
|
|
this, SLOT(configDialogShow()));
|
|
|
|
// Help menu actions
|
|
actionAbout->setIcon(icon("mupen64plus.png"));
|
|
connect(actionAbout, SIGNAL(triggered()), this, SLOT(aboutDialogShow()));
|
|
connect(actionAboutQt, SIGNAL(triggered()),
|
|
QApplication::instance(), SLOT(aboutQt()));
|
|
|
|
actionShowToolbar->setChecked(
|
|
core::config_get_bool("ToolBarVisible", TRUE)
|
|
);
|
|
actionShowFilter->setChecked(
|
|
core::config_get_bool("FilterVisible", TRUE)
|
|
);
|
|
actionShowStatusbar->setChecked(
|
|
core::config_get_bool("StatusBarVisible", TRUE)
|
|
);
|
|
|
|
m_uiActions = new QActionGroup(this);
|
|
m_uiActions->setExclusive(false);
|
|
m_uiActions->addAction(actionCloseRom);
|
|
m_uiActions->addAction(actionSaveState);
|
|
m_uiActions->addAction(actionSaveStateAs);
|
|
m_uiActions->addAction(actionLoadState);
|
|
m_uiActions->addAction(actionLoadStateFrom);
|
|
m_uiActions->addAction(actionFullScreen);
|
|
m_uiActions->addAction(actionStop);
|
|
m_uiActions->addAction(actionPause);
|
|
}
|
|
|
|
void MainWindow::setState(core::gui_state_t state)
|
|
{
|
|
bool pause, stop, play;
|
|
pause = stop = play = false;
|
|
|
|
switch (state) {
|
|
case core::GUI_STATE_RUNNING:
|
|
play = true;
|
|
break;
|
|
case core::GUI_STATE_PAUSED:
|
|
pause = true;
|
|
break;
|
|
case core::GUI_STATE_STOPPED:
|
|
stop = true;
|
|
break;
|
|
}
|
|
|
|
m_uiActions->setEnabled(!stop);
|
|
|
|
actionStart->setChecked(play);
|
|
actionPause->setChecked(pause);
|
|
actionStop->setChecked(stop);
|
|
}
|
|
|