mirror of https://github.com/mgba-emu/mgba.git
Qt: Revamp logging configuration
This commit is contained in:
parent
bd8fe4d878
commit
4e39875e7b
|
@ -194,13 +194,26 @@ typedef intptr_t ssize_t;
|
|||
#define TEST_FILL_BITS(SRC, START, END, TEST) ((TEST) ? (FILL_BITS(SRC, START, END)) : (CLEAR_BITS(SRC, START, END)))
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma section(".CRT$XCU",read)
|
||||
#define ATTRIBUTE_UNUSED
|
||||
#define ATTRIBUTE_FORMAT(X, Y, Z)
|
||||
#define ATTRIBUTE_NOINLINE
|
||||
// Adapted from https://stackoverflow.com/a/2390626
|
||||
#define _CONSTRUCTOR(FN, PRE) \
|
||||
static void FN(void); \
|
||||
__declspec(allocate(".CRT$XCU")) void (*_CONSTRUCTOR_ ## FN)(void) = FN; \
|
||||
__pragma(comment(linker,"/include:" PRE "_CONSTRUCTOR_" #FN)) \
|
||||
static void FN(void)
|
||||
#ifdef _WIN64
|
||||
#define CONSTRUCTOR(FN) _CONSTRUCTOR(FN, "")
|
||||
#else
|
||||
#define CONSTRUCTOR(FN) _CONSTRUCTOR(FN, "_")
|
||||
#endif
|
||||
#else
|
||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
#define ATTRIBUTE_FORMAT(X, Y, Z) __attribute__((format(X, Y, Z)))
|
||||
#define ATTRIBUTE_NOINLINE __attribute__((noinline))
|
||||
#define CONSTRUCTOR(FN) static __attribute__((constructor)) void FN(void)
|
||||
#endif
|
||||
|
||||
#define DECL_BITFIELD(NAME, TYPE) typedef TYPE NAME
|
||||
|
|
|
@ -47,24 +47,23 @@ struct mCoreConfig;
|
|||
void mLogFilterInit(struct mLogFilter*);
|
||||
void mLogFilterDeinit(struct mLogFilter*);
|
||||
void mLogFilterLoad(struct mLogFilter*, const struct mCoreConfig*);
|
||||
void mLogFilterSave(const struct mLogFilter*, struct mCoreConfig*);
|
||||
void mLogFilterSet(struct mLogFilter*, const char* category, int levels);
|
||||
bool mLogFilterTest(struct mLogFilter*, int category, enum mLogLevel level);
|
||||
void mLogFilterReset(struct mLogFilter*, const char* category);
|
||||
bool mLogFilterTest(const struct mLogFilter*, int category, enum mLogLevel level);
|
||||
int mLogFilterLevels(const struct mLogFilter*, int category);
|
||||
|
||||
ATTRIBUTE_FORMAT(printf, 3, 4)
|
||||
void mLog(int category, enum mLogLevel level, const char* format, ...);
|
||||
|
||||
#define mLOG(CATEGORY, LEVEL, ...) mLog(_mLOG_CAT_ ## CATEGORY (), mLOG_ ## LEVEL, __VA_ARGS__)
|
||||
#define mLOG(CATEGORY, LEVEL, ...) mLog(_mLOG_CAT_ ## CATEGORY, mLOG_ ## LEVEL, __VA_ARGS__)
|
||||
|
||||
#define mLOG_DECLARE_CATEGORY(CATEGORY) int _mLOG_CAT_ ## CATEGORY (void); extern const char* _mLOG_CAT_ ## CATEGORY ## _ID;
|
||||
#define mLOG_DECLARE_CATEGORY(CATEGORY) extern int _mLOG_CAT_ ## CATEGORY;
|
||||
#define mLOG_DEFINE_CATEGORY(CATEGORY, NAME, ID) \
|
||||
int _mLOG_CAT_ ## CATEGORY (void) { \
|
||||
static int category = 0; \
|
||||
if (!category) { \
|
||||
category = mLogGenerateCategory(NAME, ID); \
|
||||
} \
|
||||
return category; \
|
||||
} \
|
||||
const char* _mLOG_CAT_ ## CATEGORY ## _ID = ID;
|
||||
int _mLOG_CAT_ ## CATEGORY; \
|
||||
CONSTRUCTOR(_mLOG_CAT_ ## CATEGORY ## _INIT) { \
|
||||
_mLOG_CAT_ ## CATEGORY = mLogGenerateCategory(NAME, ID); \
|
||||
}
|
||||
|
||||
mLOG_DECLARE_CATEGORY(STATUS)
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ static void _setFilterLevel(const char* key, const char* value, enum mCoreConfig
|
|||
char* end;
|
||||
int ivalue = strtol(value, &end, 10);
|
||||
if (ivalue == 0) {
|
||||
ivalue = INT_MIN; // Zero is reserved
|
||||
ivalue = 0x80; // Zero is reserved
|
||||
}
|
||||
if (!end) {
|
||||
return;
|
||||
|
@ -113,34 +113,66 @@ static void _setFilterLevel(const char* key, const char* value, enum mCoreConfig
|
|||
}
|
||||
|
||||
void mLogFilterLoad(struct mLogFilter* filter, const struct mCoreConfig* config) {
|
||||
HashTableClear(&filter->categories);
|
||||
TableClear(&filter->levels);
|
||||
|
||||
mCoreConfigEnumerate(config, "logLevel.", _setFilterLevel, filter);
|
||||
filter->defaultLevels = mLOG_ALL;
|
||||
mCoreConfigGetIntValue(config, "logLevel", &filter->defaultLevels);
|
||||
}
|
||||
|
||||
void mLogFilterSave(const struct mLogFilter* filter, struct mCoreConfig* config) {
|
||||
mCoreConfigSetIntValue(config, "logLevel", filter->defaultLevels);
|
||||
int i;
|
||||
for (i = 0; i < _category; ++i) {
|
||||
char configName[128] = {0};
|
||||
snprintf(configName, sizeof(configName) - 1, "logLevel.%s", mLogCategoryId(i));
|
||||
int levels = mLogFilterLevels(filter, i);
|
||||
if (levels) {
|
||||
mCoreConfigSetIntValue(config, configName, levels & ~0x80);
|
||||
} else {
|
||||
mCoreConfigSetValue(config, configName, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mLogFilterSet(struct mLogFilter* filter, const char* category, int levels) {
|
||||
levels |= 0x80;
|
||||
HashTableInsert(&filter->categories, category, (void*)(intptr_t) levels);
|
||||
// Can't do this eagerly because not all categories are initialized immediately
|
||||
int cat = mLogCategoryById(category);
|
||||
if (cat >= 0) {
|
||||
TableInsert(&filter->levels, cat, (void*)(intptr_t) levels);
|
||||
}
|
||||
|
||||
}
|
||||
bool mLogFilterTest(struct mLogFilter* filter, int category, enum mLogLevel level) {
|
||||
int value = (intptr_t) TableLookup(&filter->levels, category);
|
||||
|
||||
void mLogFilterReset(struct mLogFilter* filter, const char* category) {
|
||||
HashTableRemove(&filter->categories, category);
|
||||
// Can't do this eagerly because not all categories are initialized immediately
|
||||
int cat = mLogCategoryById(category);
|
||||
if (cat >= 0) {
|
||||
TableRemove(&filter->levels, cat);
|
||||
}
|
||||
}
|
||||
|
||||
bool mLogFilterTest(const struct mLogFilter* filter, int category, enum mLogLevel level) {
|
||||
int value = mLogFilterLevels(filter, category);
|
||||
if (value) {
|
||||
return value & level;
|
||||
}
|
||||
const char* cat = mLogCategoryId(category);
|
||||
if (cat) {
|
||||
value = (intptr_t) HashTableLookup(&filter->categories, cat);
|
||||
if (value) {
|
||||
TableInsert(&filter->levels, category, (void*)(intptr_t) value);
|
||||
return value & level;
|
||||
}
|
||||
}
|
||||
return level & filter->defaultLevels;
|
||||
}
|
||||
|
||||
int mLogFilterLevels(const struct mLogFilter* filter , int category) {
|
||||
int value = (intptr_t) TableLookup(&filter->levels, category);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
const char* cat = mLogCategoryId(category);
|
||||
if (cat) {
|
||||
value = (intptr_t) HashTableLookup(&filter->categories, cat);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
mLOG_DEFINE_CATEGORY(STATUS, "Status", "core.status")
|
||||
|
|
|
@ -524,7 +524,7 @@ void GBADebug(struct GBA* gba, uint16_t flags) {
|
|||
strncpy(oolBuf, gba->debugString, sizeof(oolBuf) - 1);
|
||||
memset(gba->debugString, 0, sizeof(gba->debugString));
|
||||
oolBuf[0x100] = '\0';
|
||||
mLog(_mLOG_CAT_GBA_DEBUG(), level, "%s", oolBuf);
|
||||
mLog(_mLOG_CAT_GBA_DEBUG, level, "%s", oolBuf);
|
||||
}
|
||||
gba->debugFlags = GBADebugFlagsClearSend(gba->debugFlags);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ set(SOURCE_FILES
|
|||
KeyEditor.cpp
|
||||
LoadSaveState.cpp
|
||||
LogController.cpp
|
||||
LogConfigModel.cpp
|
||||
LogView.cpp
|
||||
MapView.cpp
|
||||
MemoryModel.cpp
|
||||
|
@ -104,6 +105,7 @@ set(SOURCE_FILES
|
|||
PrinterView.cpp
|
||||
RegisterView.cpp
|
||||
ROMInfo.cpp
|
||||
RotatedHeaderView.cpp
|
||||
SavestateButton.cpp
|
||||
SensorView.cpp
|
||||
SettingsView.cpp
|
||||
|
|
|
@ -82,7 +82,8 @@ public:
|
|||
|
||||
Configuration* input() { return mCoreConfigGetInput(&m_config); }
|
||||
|
||||
const mCoreConfig* config() { return &m_config; }
|
||||
const mCoreConfig* config() const { return &m_config; }
|
||||
mCoreConfig* config() { return &m_config; }
|
||||
|
||||
static const QString& configDir();
|
||||
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
#include "CoreManager.h"
|
||||
#include "ConfigController.h"
|
||||
#include "Display.h"
|
||||
#include "Window.h"
|
||||
#include "LogController.h"
|
||||
#include "VFileDevice.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QFileOpenEvent>
|
||||
|
@ -65,6 +66,8 @@ GBAApp::GBAApp(int& argc, char* argv[], ConfigController* config)
|
|||
AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController->getQtOption("audioDriver").toInt()));
|
||||
}
|
||||
|
||||
LogController::global()->load(m_configController);
|
||||
|
||||
connect(this, &GBAApp::aboutToQuit, this, &GBAApp::cleanup);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "LogConfigModel.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
LogConfigModel::LogConfigModel(LogController* controller, QObject* parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, m_controller(controller)
|
||||
{
|
||||
for (int i = 0; mLogCategoryId(i); ++i) {
|
||||
int levels = controller->levels(i);
|
||||
m_cache.append({ i, mLogCategoryName(i), mLogCategoryId(i), levels ? levels : -1 });
|
||||
}
|
||||
std::sort(m_cache.begin(), m_cache.end());
|
||||
m_levels = m_controller->levels();
|
||||
}
|
||||
|
||||
QVariant LogConfigModel::data(const QModelIndex& index, int role) const {
|
||||
if (role != Qt::CheckStateRole) {
|
||||
return QVariant();
|
||||
}
|
||||
int levels;
|
||||
if (index.row() == 0) {
|
||||
levels = m_levels;
|
||||
} else {
|
||||
levels = m_cache[index.row() - 1].levels;
|
||||
}
|
||||
if (index.column() == 0) {
|
||||
return levels < 0 ? Qt::Checked : Qt::Unchecked;
|
||||
} else if (levels < 0 && index.row() > 0) {
|
||||
return (m_levels >> (index.column() - 1)) & 1 ? Qt::PartiallyChecked : Qt::Unchecked;
|
||||
} else {
|
||||
return (levels >> (index.column() - 1)) & 1 ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
}
|
||||
|
||||
bool LogConfigModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||
if (role != Qt::CheckStateRole) {
|
||||
return false;
|
||||
}
|
||||
int levels;
|
||||
if (index.row() == 0) {
|
||||
levels = m_levels;
|
||||
} else {
|
||||
levels = m_cache[index.row() - 1].levels;
|
||||
}
|
||||
if (index.column() == 0) {
|
||||
levels = -1;
|
||||
} else {
|
||||
if (levels < 0) {
|
||||
levels = m_levels;
|
||||
}
|
||||
levels ^= 1 << (index.column() - 1);
|
||||
}
|
||||
if (index.row() == 0) {
|
||||
beginResetModel();
|
||||
m_levels = levels;
|
||||
endResetModel();
|
||||
} else {
|
||||
m_cache[index.row() - 1].levels = levels;
|
||||
emit dataChanged(createIndex(0, index.row(), nullptr), createIndex(8, index.row(), nullptr));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant LogConfigModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
if (role != Qt::DisplayRole) {
|
||||
return QVariant();
|
||||
}
|
||||
if (orientation == Qt::Horizontal) {
|
||||
switch (section) {
|
||||
case 0:
|
||||
return tr("Default");
|
||||
case 1:
|
||||
return tr("Fatal");
|
||||
case 2:
|
||||
return tr("Error");
|
||||
case 3:
|
||||
return tr("Warning");
|
||||
case 4:
|
||||
return tr("Info");
|
||||
case 5:
|
||||
return tr("Debug");
|
||||
case 6:
|
||||
return tr("Stub");
|
||||
case 7:
|
||||
return tr("Game Error");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
} else if (section) {
|
||||
return m_cache[section - 1].name;
|
||||
} else {
|
||||
return tr("Default");
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex LogConfigModel::index(int row, int column, const QModelIndex& parent) const {
|
||||
return createIndex(row, column, nullptr);
|
||||
}
|
||||
|
||||
QModelIndex LogConfigModel::parent(const QModelIndex& index) const {
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int LogConfigModel::columnCount(const QModelIndex& parent) const {
|
||||
return 8;
|
||||
}
|
||||
|
||||
int LogConfigModel::rowCount(const QModelIndex& parent) const {
|
||||
return m_cache.size() + 1;
|
||||
}
|
||||
|
||||
Qt::ItemFlags LogConfigModel::flags(const QModelIndex& index) const {
|
||||
if (!index.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
void LogConfigModel::reset() {
|
||||
beginResetModel();
|
||||
for (auto& row : m_cache) {
|
||||
row.levels = m_controller->levels(row.index);
|
||||
if (!row.levels) {
|
||||
row.levels = -1;
|
||||
}
|
||||
}
|
||||
m_levels = m_controller->levels();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void LogConfigModel::save(ConfigController* config) {
|
||||
for (auto& row : m_cache) {
|
||||
if (row.levels < 0) {
|
||||
m_controller->clearLevels(row.index);
|
||||
} else {
|
||||
m_controller->setLevels(row.levels, row.index);
|
||||
}
|
||||
}
|
||||
m_controller->setLevels(m_levels);
|
||||
m_controller->save(config);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "LogController.h"
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class ConfigController;
|
||||
|
||||
class LogConfigModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LogConfigModel(LogController*, QObject* parent = nullptr);
|
||||
|
||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex& parent) const override;
|
||||
virtual QModelIndex parent(const QModelIndex& index) const override;
|
||||
|
||||
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
void save(ConfigController*);
|
||||
|
||||
private:
|
||||
struct ConfigSetting {
|
||||
int index;
|
||||
QString name;
|
||||
const char* id;
|
||||
int levels;
|
||||
|
||||
bool operator<(struct ConfigSetting& other) {
|
||||
return name < other.name;
|
||||
}
|
||||
};
|
||||
|
||||
LogController* m_controller;
|
||||
|
||||
QList<ConfigSetting> m_cache;
|
||||
int m_levels;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "LogController.h"
|
||||
|
||||
#include "ConfigController.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
LogController LogController::s_global(mLOG_ALL);
|
||||
|
@ -19,9 +21,9 @@ LogController::LogController(int levels, QObject* parent)
|
|||
|
||||
if (this != &s_global) {
|
||||
connect(&s_global, &LogController::logPosted, this, &LogController::postLog);
|
||||
connect(this, &LogController::levelsSet, &s_global, &LogController::setLevels);
|
||||
connect(this, &LogController::levelsEnabled, &s_global, &LogController::enableLevels);
|
||||
connect(this, &LogController::levelsDisabled, &s_global, &LogController::disableLevels);
|
||||
connect(this, static_cast<void (LogController::*)(int)>(&LogController::levelsSet), &s_global, static_cast<void (LogController::*)(int)>(&LogController::setLevels));
|
||||
connect(this, static_cast<void (LogController::*)(int)>(&LogController::levelsEnabled), &s_global, static_cast<void (LogController::*)(int)>(&LogController::enableLevels));
|
||||
connect(this, static_cast<void (LogController::*)(int)>(&LogController::levelsDisabled), &s_global, static_cast<void (LogController::*)(int)>(&LogController::disableLevels));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,10 +31,22 @@ LogController::~LogController() {
|
|||
mLogFilterDeinit(&m_filter);
|
||||
}
|
||||
|
||||
int LogController::levels(int category) const {
|
||||
return mLogFilterLevels(&m_filter, category);
|
||||
}
|
||||
|
||||
LogController::Stream LogController::operator()(int category, int level) {
|
||||
return Stream(this, category, level);
|
||||
}
|
||||
|
||||
void LogController::load(const ConfigController* config) {
|
||||
mLogFilterLoad(&m_filter, config->config());
|
||||
}
|
||||
|
||||
void LogController::save(ConfigController* config) const {
|
||||
mLogFilterSave(&m_filter, config->config());
|
||||
}
|
||||
|
||||
void LogController::postLog(int level, int category, const QString& string) {
|
||||
if (!mLogFilterTest(&m_filter, category, static_cast<mLogLevel>(level))) {
|
||||
return;
|
||||
|
@ -55,6 +69,31 @@ void LogController::disableLevels(int levels) {
|
|||
emit levelsDisabled(levels);
|
||||
}
|
||||
|
||||
void LogController::setLevels(int levels, int category) {
|
||||
auto id = mLogCategoryId(category);
|
||||
mLogFilterSet(&m_filter, id, levels);
|
||||
emit levelsSet(levels, category);
|
||||
}
|
||||
|
||||
void LogController::enableLevels(int levels, int category) {
|
||||
auto id = mLogCategoryId(category);
|
||||
int newLevels = mLogFilterLevels(&m_filter, category) | levels;
|
||||
mLogFilterSet(&m_filter, id, newLevels);
|
||||
emit levelsEnabled(levels, category);
|
||||
}
|
||||
|
||||
void LogController::disableLevels(int levels, int category) {
|
||||
auto id = mLogCategoryId(category);
|
||||
int newLevels = mLogFilterLevels(&m_filter, category) & ~levels;
|
||||
mLogFilterSet(&m_filter, id, newLevels);
|
||||
emit levelsDisabled(levels, category);
|
||||
}
|
||||
|
||||
void LogController::clearLevels(int category) {
|
||||
auto id = mLogCategoryId(category);
|
||||
mLogFilterReset (&m_filter, id);
|
||||
}
|
||||
|
||||
LogController* LogController::global() {
|
||||
return &s_global;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
namespace QGBA {
|
||||
|
||||
class ConfigController;
|
||||
|
||||
class LogController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -38,24 +40,36 @@ public:
|
|||
~LogController();
|
||||
|
||||
int levels() const { return m_filter.defaultLevels; }
|
||||
int levels(int category) const;
|
||||
mLogFilter* filter() { return &m_filter; }
|
||||
|
||||
Stream operator()(int category, int level);
|
||||
|
||||
static LogController* global();
|
||||
static QString toString(int level);
|
||||
static int categoryId(const char*);
|
||||
|
||||
void load(const ConfigController*);
|
||||
void save(ConfigController*) const;
|
||||
|
||||
signals:
|
||||
void logPosted(int level, int category, const QString& log);
|
||||
void levelsSet(int levels);
|
||||
void levelsEnabled(int levels);
|
||||
void levelsDisabled(int levels);
|
||||
void levelsSet(int levels, int category);
|
||||
void levelsEnabled(int levels, int category);
|
||||
void levelsDisabled(int levels, int category);
|
||||
|
||||
public slots:
|
||||
void postLog(int level, int category, const QString& string);
|
||||
void setLevels(int levels);
|
||||
void enableLevels(int levels);
|
||||
void disableLevels(int levels);
|
||||
void setLevels(int levels, int category);
|
||||
void enableLevels(int levels, int category);
|
||||
void disableLevels(int levels, int category);
|
||||
void clearLevels(int category);
|
||||
|
||||
private:
|
||||
mLogFilter m_filter;
|
||||
|
@ -63,6 +77,6 @@ private:
|
|||
static LogController s_global;
|
||||
};
|
||||
|
||||
#define LOG(C, L) (*LogController::global())(mLOG_ ## L, _mLOG_CAT_ ## C ())
|
||||
#define LOG(C, L) (*LogController::global())(mLOG_ ## L, _mLOG_CAT_ ## C)
|
||||
|
||||
}
|
||||
|
|
|
@ -43,19 +43,19 @@ LogView::LogView(LogController* log, QWidget* parent)
|
|||
m_ui.maxLines->setValue(DEFAULT_LINE_LIMIT);
|
||||
|
||||
connect(log, &LogController::logPosted, this, &LogView::postLog);
|
||||
connect(log, &LogController::levelsSet, this, &LogView::setLevels);
|
||||
connect(log, &LogController::levelsEnabled, [this](int level) {
|
||||
connect(log, static_cast<void (LogController::*)(int)>(&LogController::levelsSet), this, &LogView::setLevels);
|
||||
connect(log, static_cast<void (LogController::*)(int)>(&LogController::levelsEnabled), [this](int level) {
|
||||
bool s = blockSignals(true);
|
||||
setLevel(level, true);
|
||||
blockSignals(s);
|
||||
});
|
||||
connect(log, &LogController::levelsDisabled, [this](int level) {
|
||||
connect(log, static_cast<void (LogController::*)(int)>(&LogController::levelsDisabled), [this](int level) {
|
||||
bool s = blockSignals(true);
|
||||
setLevel(level, false);
|
||||
blockSignals(s);
|
||||
});
|
||||
connect(this, &LogView::levelsEnabled, log, &LogController::enableLevels);
|
||||
connect(this, &LogView::levelsDisabled, log, &LogController::disableLevels);
|
||||
connect(this, &LogView::levelsEnabled, log, static_cast<void (LogController::*)(int)>(&LogController::enableLevels));
|
||||
connect(this, &LogView::levelsDisabled, log, static_cast<void (LogController::*)(int)>(&LogController::disableLevels));
|
||||
}
|
||||
|
||||
void LogView::postLog(int level, int category, const QString& log) {
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "RotatedHeaderView.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
RotatedHeaderView::RotatedHeaderView(Qt::Orientation orientation, QWidget* parent)
|
||||
: QHeaderView(orientation, parent)
|
||||
{
|
||||
}
|
||||
|
||||
void RotatedHeaderView::paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const {
|
||||
painter->save();
|
||||
painter->translate(rect.x() + rect.width(), rect.y());
|
||||
painter->rotate(90);
|
||||
QHeaderView::paintSection(painter, QRect(0, 0, rect.height(), rect.width()), logicalIndex);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize RotatedHeaderView::sectionSizeFromContents(int logicalIndex) const {
|
||||
return QHeaderView::sectionSizeFromContents(logicalIndex).transposed();
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class RotatedHeaderView : public QHeaderView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RotatedHeaderView(Qt::Orientation orientation, QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const;
|
||||
virtual QSize sectionSizeFromContents(int logicalIndex) const override;
|
||||
};
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include "GBAApp.h"
|
||||
#include "GBAKeyEditor.h"
|
||||
#include "InputController.h"
|
||||
#include "RotatedHeaderView.h"
|
||||
#include "ShaderSelector.h"
|
||||
#include "ShortcutView.h"
|
||||
|
||||
|
@ -24,9 +25,10 @@ using namespace QGBA;
|
|||
QList<enum GBModel> SettingsView::s_gbModelList;
|
||||
#endif
|
||||
|
||||
SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, QWidget* parent)
|
||||
SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent)
|
||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||
, m_controller(controller)
|
||||
, m_logModel(logController)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
|
@ -293,6 +295,11 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
}
|
||||
}
|
||||
|
||||
m_ui.loggingView->setModel(&m_logModel);
|
||||
m_ui.loggingView->setHorizontalHeader(new RotatedHeaderView(Qt::Horizontal));
|
||||
m_ui.loggingView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
m_ui.loggingView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
ShortcutView* shortcutView = new ShortcutView();
|
||||
shortcutView->setController(shortcutController);
|
||||
shortcutView->setInputController(inputController);
|
||||
|
@ -430,6 +437,8 @@ void SettingsView::updateConfig() {
|
|||
emit languageChanged();
|
||||
}
|
||||
|
||||
m_logModel.save(m_controller);
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
GBModel modelGB = s_gbModelList[m_ui.gbModel->currentIndex()];
|
||||
m_controller->setOption("gb.model", GBModelToName(modelGB));
|
||||
|
@ -535,6 +544,8 @@ void SettingsView::reloadConfig() {
|
|||
m_ui.saveStateSave->setChecked(saveState & SAVESTATE_SAVEDATA);
|
||||
m_ui.saveStateCheats->setChecked(saveState & SAVESTATE_CHEATS);
|
||||
|
||||
m_logModel.reset();
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
QString modelGB = m_controller->getOption("gb.model");
|
||||
if (!modelGB.isNull()) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "ColorPicker.h"
|
||||
#include "LogConfigModel.h"
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
|
||||
|
@ -28,7 +29,7 @@ class SettingsView : public QDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, QWidget* parent = nullptr);
|
||||
SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent = nullptr);
|
||||
~SettingsView();
|
||||
|
||||
void setShaderSelector(ShaderSelector* shaderSelector);
|
||||
|
@ -53,6 +54,7 @@ private:
|
|||
ConfigController* m_controller;
|
||||
InputController* m_input;
|
||||
ShaderSelector* m_shader = nullptr;
|
||||
LogConfigModel m_logModel;
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
uint32_t m_gbColors[12]{};
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QListWidget" name="tabs">
|
||||
<property name="sizePolicy">
|
||||
|
@ -65,6 +72,11 @@
|
|||
<string>Paths</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Logging</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy</string>
|
||||
|
@ -72,17 +84,10 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="av">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
|
@ -1205,6 +1210,20 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="logging">
|
||||
<layout class="QGridLayout" name="a">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableView" name="loggingView">
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>0</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||
<number>0</number>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="gb">
|
||||
<layout class="QFormLayout" name="formLayout_1">
|
||||
<item row="0" column="0">
|
||||
|
|
|
@ -141,6 +141,7 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi
|
|||
connect(&m_inputController, &InputController::profileLoaded, m_shortcutController, &ShortcutController::loadProfile);
|
||||
|
||||
m_log.setLevels(mLOG_WARN | mLOG_ERROR | mLOG_FATAL);
|
||||
m_log.load(m_config);
|
||||
m_fpsTimer.setInterval(FPS_TIMER_INTERVAL);
|
||||
m_focusCheck.setInterval(200);
|
||||
|
||||
|
@ -432,7 +433,7 @@ void Window::exportSharkport() {
|
|||
}
|
||||
|
||||
void Window::openSettingsWindow() {
|
||||
SettingsView* settingsWindow = new SettingsView(m_config, &m_inputController, m_shortcutController);
|
||||
SettingsView* settingsWindow = new SettingsView(m_config, &m_inputController, m_shortcutController, &m_log);
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
if (m_display->supportsShaders()) {
|
||||
settingsWindow->setShaderSelector(m_shaderView.get());
|
||||
|
|
|
@ -111,7 +111,9 @@ void TableInsert(struct Table* table, uint32_t key, void* value) {
|
|||
struct TableList* list;
|
||||
TABLE_LOOKUP_START(TABLE_COMPARATOR, list, key) {
|
||||
if (value != lookupResult->value) {
|
||||
table->deinitializer(lookupResult->value);
|
||||
if (table->deinitializer) {
|
||||
table->deinitializer(lookupResult->value);
|
||||
}
|
||||
lookupResult->value = value;
|
||||
}
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue