all repos — mgba @ fa255dc808d507875966626a09f67106bfbca47a

mGBA Game Boy Advance Emulator

Start of log view
Jeffrey Pfau jeffrey@endrift.com
Mon, 13 Oct 2014 01:48:24 -0700
commit

fa255dc808d507875966626a09f67106bfbca47a

parent

eef1a5e8a3a98f1b889eeae3791bc324b16edf88

M src/platform/qt/CMakeLists.txtsrc/platform/qt/CMakeLists.txt

@@ -22,7 +22,16 @@ set(BUILD_QT OFF PARENT_SCOPE)

return() endif() -set(SOURCE_FILES AudioDevice.cpp AudioProcessor.cpp Display.cpp GameController.cpp Window.cpp) +set(SOURCE_FILES + AudioDevice.cpp + AudioProcessor.cpp + Display.cpp + GameController.cpp + LogView.cpp + Window.cpp) + +qt5_wrap_ui(UI_FILES + LogView.ui) if(USE_GDB_STUB) set(SOURCE_FILES ${PLATFORM_SRC} ${SOURCE_FILES} GDBController.cpp GDBWindow.cpp)

@@ -31,7 +40,7 @@ set(MACOSX_BUNDLE_ICON_FILE mgba.icns)

set(MACOSX_BUNDLE_BUNDLE_VERSION ${LIB_VERSION_STRING}) set_source_files_properties(${CMAKE_SOURCE_DIR}/res/mgba.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) -add_executable(mGBA WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES}) +add_executable(mGBA WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES} ${UI_FILES}) qt5_use_modules(mGBA Widgets Multimedia OpenGL) target_link_libraries(mGBA ${PLATFORM_LIBRARY} ${OPENGL_LIBRARY} ${BINARY_NAME} Qt5::Widgets)
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -32,7 +32,8 @@ .frameskip = 0,

.bios = 0, .renderer = &m_renderer->d, .userData = this, - .rewindBufferCapacity = 0 + .rewindBufferCapacity = 0, + .logLevel = -1, }; GBAInputMapInit(&m_threadContext.inputMap);

@@ -65,6 +66,11 @@ controller->gamePaused(&controller->m_threadContext);

} controller->m_pauseMutex.unlock(); controller->frameAvailable(controller->m_drawContext); + }; + + m_threadContext.logHandler = [] (GBAThread* context, enum GBALogLevel level, const char* format, va_list args) { + GameController* controller = static_cast<GameController*>(context->userData); + controller->postLog(level, QString().vsprintf(format, args)); }; m_audioThread->start();
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -46,6 +46,8 @@ void gameStopped(GBAThread*);

void gamePaused(GBAThread*); void gameUnpaused(GBAThread*); + void postLog(int level, const QString& log); + public slots: void loadGame(const QString& path); void closeGame();
A src/platform/qt/LogView.cpp

@@ -0,0 +1,98 @@

+#include "LogView.h" + +using namespace QGBA; + +LogView::LogView(QWidget* parent) + : QWidget(parent) +{ + m_ui.setupUi(this); + connect(m_ui.levelDebug, SIGNAL(toggled(bool)), this, SLOT(setLevelDebug(bool))); + connect(m_ui.levelStub, SIGNAL(toggled(bool)), this, SLOT(setLevelStub(bool))); + connect(m_ui.levelInfo, SIGNAL(toggled(bool)), this, SLOT(setLevelInfo(bool))); + connect(m_ui.levelWarn, SIGNAL(toggled(bool)), this, SLOT(setLevelWarn(bool))); + connect(m_ui.levelError, SIGNAL(toggled(bool)), this, SLOT(setLevelError(bool))); + connect(m_ui.levelFatal, SIGNAL(toggled(bool)), this, SLOT(setLevelFatal(bool))); + connect(m_ui.levelGameError, SIGNAL(toggled(bool)), this, SLOT(setLevelGameError(bool))); + m_logLevel = -1; +} + +void LogView::postLog(int level, const QString& log) { + if (!(level & m_logLevel)) { + return; + } + m_ui.view->appendPlainText(QString("%1:\t%2").arg(toString(level)).arg(log)); +} + +void LogView::clear() { + m_ui.view->clear(); +} + +void LogView::setLevelDebug(bool set) { + if (set) { + setLevel(GBA_LOG_DEBUG); + } else { + clearLevel(GBA_LOG_DEBUG); + } +} +void LogView::setLevelStub(bool set) { + if (set) { + setLevel(GBA_LOG_STUB); + } else { + clearLevel(GBA_LOG_STUB); + } +} +void LogView::setLevelInfo(bool set) { + if (set) { + setLevel(GBA_LOG_INFO); + } else { + clearLevel(GBA_LOG_INFO); + } +} +void LogView::setLevelWarn(bool set) { + if (set) { + setLevel(GBA_LOG_WARN); + } else { + clearLevel(GBA_LOG_WARN); + } +} +void LogView::setLevelError(bool set) { + if (set) { + setLevel(GBA_LOG_ERROR); + } else { + clearLevel(GBA_LOG_ERROR); + } +} +void LogView::setLevelFatal(bool set) { + if (set) { + setLevel(GBA_LOG_FATAL); + } else { + clearLevel(GBA_LOG_FATAL); + } +} +void LogView::setLevelGameError(bool set) { + if (set) { + setLevel(GBA_LOG_GAME_ERROR); + } else { + clearLevel(GBA_LOG_GAME_ERROR); + } +} + +QString LogView::toString(int level) { + switch (level) { + case GBA_LOG_DEBUG: + return tr("DEBUG"); + case GBA_LOG_STUB: + return tr("STUB"); + case GBA_LOG_INFO: + return tr("INFO"); + case GBA_LOG_WARN: + return tr("WARN"); + case GBA_LOG_ERROR: + return tr("ERROR"); + case GBA_LOG_FATAL: + return tr("FATAL"); + case GBA_LOG_GAME_ERROR: + return tr("GAME ERROR"); + } + return QString(); +}
A src/platform/qt/LogView.h

@@ -0,0 +1,44 @@

+#ifndef QGBA_LOG_VIEW +#define QGBA_LOG_VIEW + +#include <QWidget> + +#include "ui_LogView.h" + +extern "C" { +#include "gba-thread.h" +} + +namespace QGBA { + +class LogView : public QWidget { +Q_OBJECT + +public: + LogView(QWidget* parent = nullptr); + +public slots: + void postLog(int level, const QString& log); + void clear(); + +private slots: + void setLevelDebug(bool); + void setLevelStub(bool); + void setLevelInfo(bool); + void setLevelWarn(bool); + void setLevelError(bool); + void setLevelFatal(bool); + void setLevelGameError(bool); + +private: + Ui::LogView m_ui; + int m_logLevel; + + static QString toString(int level); + void setLevel(int level) { m_logLevel |= level; } + void clearLevel(int level) { m_logLevel &= ~level; } +}; + +} + +#endif
A src/platform/qt/LogView.ui

@@ -0,0 +1,164 @@

+<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LogView</class> + <widget class="QWidget" name="LogView"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle"> + <string>Logs</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string/> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="levelDebug"> + <property name="text"> + <string>Debug</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="levelStub"> + <property name="text"> + <string>Stub</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="levelInfo"> + <property name="text"> + <string>Info</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="levelWarn"> + <property name="text"> + <string>Warning</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="levelError"> + <property name="text"> + <string>Error</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="levelFatal"> + <property name="text"> + <string>Fatal</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="levelGameError"> + <property name="text"> + <string>Game Error</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QPushButton" name="clear"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPlainTextEdit" name="view"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>clear</sender> + <signal>clicked()</signal> + <receiver>view</receiver> + <slot>clear()</slot> + <hints> + <hint type="sourcelabel"> + <x>98</x> + <y>376</y> + </hint> + <hint type="destinationlabel"> + <x>299</x> + <y>311</y> + </hint> + </hints> + </connection> + </connections> +</ui>
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -8,6 +8,7 @@

#include "GameController.h" #include "GDBWindow.h" #include "GDBController.h" +#include "LogView.h" using namespace QGBA;

@@ -21,17 +22,24 @@ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

setMinimumSize(240, 160); m_controller = new GameController(this); + m_logView = new LogView(); m_display = new Display(); setCentralWidget(m_display); connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*))); connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_display, SLOT(stopDrawing())); connect(m_controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped())); + connect(m_controller, SIGNAL(postLog(int, const QString&)), m_logView, SLOT(postLog(int, const QString&))); connect(this, SIGNAL(startDrawing(const uint32_t*, GBAThread*)), m_display, SLOT(startDrawing(const uint32_t*, GBAThread*)), Qt::QueuedConnection); connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing())); + connect(this, SIGNAL(shutdown()), m_controller, SLOT(closeGame())); connect(this, SIGNAL(audioBufferSamplesChanged(int)), m_controller, SLOT(setAudioBufferSamples(int))); connect(this, SIGNAL(fpsTargetChanged(float)), m_controller, SLOT(setFPSTarget(float))); setupMenu(menuBar()); +} + +Window::~Window() { + delete m_logView; } GBAKey Window::mapKey(int qtKey) {

@@ -232,6 +240,9 @@ connect(setBuffer, &QAction::triggered, [this]() { emit audioBufferSamplesChanged(2048); });

buffersMenu->addAction(setBuffer); QMenu* debuggingMenu = menubar->addMenu(tr("&Debugging")); + QAction* viewLogs = new QAction(tr("View &logs..."), nullptr); + connect(viewLogs, SIGNAL(triggered()), m_logView, SLOT(show())); + debuggingMenu->addAction(viewLogs); #ifdef USE_GDB_STUB QAction* gdbWindow = new QAction(tr("Start &GDB server..."), nullptr); connect(gdbWindow, SIGNAL(triggered()), this, SLOT(gdbOpen()));
M src/platform/qt/Window.hsrc/platform/qt/Window.h

@@ -14,12 +14,15 @@ namespace QGBA {

class GameController; class GDBController; +class LogView; class Window : public QMainWindow { Q_OBJECT public: Window(QWidget* parent = nullptr); + virtual ~Window(); + static GBAKey mapKey(int qtKey); signals:

@@ -51,6 +54,7 @@ void setupMenu(QMenuBar*);

GameController* m_controller; Display* m_display; QList<QAction*> m_gameActions; + LogView* m_logView; #ifdef USE_GDB_STUB GDBController* m_gdbController;