Skip to content

Commit

Permalink
Qt/GameConfigWidget: Complete overhaul
Browse files Browse the repository at this point in the history
  • Loading branch information
spycrab committed Jul 13, 2018
1 parent fc96790 commit 2d05990
Show file tree
Hide file tree
Showing 8 changed files with 338 additions and 367 deletions.
2 changes: 2 additions & 0 deletions Source/Core/DolphinQt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ add_executable(dolphin-emu
Config/CheatWarningWidget.cpp
Config/ControllersWindow.cpp
Config/FilesystemWidget.cpp
Config/GameConfigEdit.cpp
Config/GameConfigHighlighter.cpp
Config/GameConfigWidget.cpp
Config/GeckoCodeWidget.cpp
Config/Graphics/AdvancedWidget.cpp
Expand Down
168 changes: 168 additions & 0 deletions Source/Core/DolphinQt/Config/GameConfigEdit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "DolphinQt/Config/GameConfigEdit.h"

#include <QCompleter>
#include <QDesktopServices>
#include <QFile>
#include <QMenu>
#include <QTextCursor>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QWhatsThis>

#include "DolphinQt/Config/GameConfigHighlighter.h"

GameConfigEdit::GameConfigEdit(QWidget* parent, const QString& path) : m_path(path)
{
LoadFile();

setAcceptRichText(false);
setContextMenuPolicy(Qt::CustomContextMenu);

new GameConfigHighlighter(document());

m_keyword_map[QStringLiteral("Core")] =
tr("Section that contains most CPU and Hardware related settings.");

m_keyword_map[QStringLiteral("CPUThread")] = tr(
"Controls whether or not Dual Core should be enabled. Can improve performance but can also "
"cause issues. Defaults to <b>True</b>");
m_keyword_map[QStringLiteral("FastDiscSpeed")] =
tr("Shortens loading times but may break some games. Can have negative effects on performance. Defaults to <b>False</b>");
m_keyword_map[QStringLiteral("MMU")] = tr("Controls whether or not the Memory Management Unit "
"should be emulated fully. Few games require it.");
m_keyword_map[QStringLiteral("DSPHLE")] =
tr("Controls whether to use high or low-level DSP emulation. Defaults to <b>True</b>");
m_keyword_map[QStringLiteral("JITFollowBranch")] =
tr("Tries to translate branches ahead of time, improving performance in most cases. Defaults "
"to <b>True</b>");

m_keyword_map[QStringLiteral("Gecko")] = tr("Section that contains all Gecko cheat codes.");
m_keyword_map[QStringLiteral("ActionReplay")] =
tr("Section that contains all Action Replay cheat codes.");
m_keyword_map[QStringLiteral("Video_Settings")] =
tr("Section that contains all graphics related settings.");

Connect();
}

void GameConfigEdit::LoadFile()
{
QFile file(m_path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;

setPlainText(QString::fromStdString(file.readAll().toStdString()));
}

#include <iostream>

void GameConfigEdit::SaveFile()
{
if (!isVisible() || isReadOnly())
return;

QFile file(m_path);

if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
return;

const std::string contents = toPlainText().toStdString();

file.write(contents.c_str(), contents.length());
}

void GameConfigEdit::Connect()
{
connect(this, &QTextEdit::textChanged, this, &GameConfigEdit::SaveFile);
connect(this, &QTextEdit::selectionChanged, this, &GameConfigEdit::OnSelectionChanged);
connect(this, &QTextEdit::customContextMenuRequested, this, &GameConfigEdit::OnContextMenu);
}

void GameConfigEdit::OnSelectionChanged()
{
const QString& keyword = textCursor().selectedText();

if (m_keyword_map.count(keyword))
QWhatsThis::showText(QCursor::pos(), m_keyword_map[keyword], this);
}

void GameConfigEdit::AddBoolOption(QMenu* menu, const QString& name, const QString& section,
const QString& key)
{
auto* option = menu->addMenu(name);

option->addAction(tr("On"), this,
[this, section, key] { SetOption(section, key, QStringLiteral("True")); });
option->addAction(tr("Off"), this,
[this, section, key] { SetOption(section, key, QStringLiteral("False")); });
}

void GameConfigEdit::SetOption(const QString& section, const QString& key, const QString& value)
{
auto section_cursor = document()->find(QRegExp(QStringLiteral("^\\[%1\\]").arg(section)), 0);

// Check if the section this belongs in can be found
if (!section_cursor.isNull())
{
auto value_cursor =
document()->find(QRegExp(QStringLiteral("^%1 = .*").arg(key)), section_cursor);

const QString new_line = QStringLiteral("%1 = %2").arg(key).arg(value);

// Check if the value that has to be set already exists
if (!value_cursor.isNull())
{
value_cursor.insertText(new_line);
}
else
{
section_cursor.clearSelection();
section_cursor.insertText(QStringLiteral("\n") + new_line);
}
}
else
{
append(QStringLiteral("[%1]\n\n%2 = %3\n").arg(section).arg(key).arg(value));
}
}

void GameConfigEdit::OnContextMenu(const QPoint& pos)
{
auto* menu = createStandardContextMenu(pos);

menu->addSeparator();

menu->addAction(tr("Refresh"), this, &GameConfigEdit::LoadFile);
menu->addAction(tr("Open in External Editor"), this, &GameConfigEdit::OpenExternalEditor);

if (!isReadOnly())
{
menu->addSeparator();
auto* core_menu = menu->addMenu(tr("Core"));

AddBoolOption(core_menu, tr("Dual Core"), QStringLiteral("Core"), QStringLiteral("CPUThread"));
AddBoolOption(core_menu, tr("MMU"), QStringLiteral("Core"), QStringLiteral("MMU"));
}

menu->exec(QCursor::pos());
}

void GameConfigEdit::OpenExternalEditor()
{
QFile file(m_path);

if (!file.exists())
{
if (isReadOnly())
return;

file.open(QIODevice::WriteOnly);
file.close();
}

QDesktopServices::openUrl(QUrl::fromLocalFile(m_path));
}
39 changes: 39 additions & 0 deletions Source/Core/DolphinQt/Config/GameConfigEdit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include <vector>

#include <QMap>
#include <QString>
#include <QTextEdit>

class GameConfigEdit : public QTextEdit
{
public:
explicit GameConfigEdit(QWidget* parent, const QString& path);

private:
void Connect();

void LoadFile();
void SaveFile();

void OnSelectionChanged();
void OnContextMenu(const QPoint& pos);
void OpenExternalEditor();

void SetReadOnly(bool read_only);

void AddBoolOption(QMenu* menu, const QString& name, const QString& section, const QString& key);

void SetOption(const QString& section, const QString& key, const QString& value);

QTextEdit* m_edit;

const QString m_path;

QMap<QString, QString> m_keyword_map;
};
49 changes: 49 additions & 0 deletions Source/Core/DolphinQt/Config/GameConfigHighlighter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "DolphinQt/Config/GameConfigHighlighter.h"

GameConfigHighlighter::GameConfigHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent)
{
QTextCharFormat equal_format;
equal_format.setForeground(Qt::red);

QTextCharFormat section_format;
section_format.setFontWeight(QFont::Bold);

QTextCharFormat comment_format;
comment_format.setForeground(Qt::green);
comment_format.setFontItalic(true);

QTextCharFormat const_format;
const_format.setFontWeight(QFont::Bold);
const_format.setForeground(Qt::blue);

QTextCharFormat num_format;
num_format.setForeground(Qt::darkBlue);

m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("=")), equal_format});
m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^\\[.*?\\]")), section_format});
m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("\\bTrue\\b")), const_format});
m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("\\bFalse\\b")), const_format});
m_rules.append(
HighlightingRule{QRegularExpression(QStringLiteral("\\b[0-9a-fA-F]+\\b")), num_format});

m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^#.*")), comment_format});
m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^\\$.*")), comment_format});
m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^\\*.*")), comment_format});
}

void GameConfigHighlighter::highlightBlock(const QString& text)
{
for (const auto& rule : m_rules)
{
auto it = rule.pattern.globalMatch(text);
while (it.hasNext())
{
auto match = it.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
}
29 changes: 29 additions & 0 deletions Source/Core/DolphinQt/Config/GameConfigHighlighter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include <QRegularExpression>
#include <QSyntaxHighlighter>
#include <QTextCharFormat>

class GameConfigHighlighter : public QSyntaxHighlighter
{
Q_OBJECT

public:
GameConfigHighlighter(QTextDocument* parent = nullptr);

protected:
void highlightBlock(const QString& text) override;

private:
struct HighlightingRule
{
QRegularExpression pattern;
QTextCharFormat format;
};

QVector<HighlightingRule> m_rules;
};
Loading

0 comments on commit 2d05990

Please sign in to comment.