Add 'Open in JSON' actions

This commit is contained in:
GriffinR
2025-05-08 20:43:52 -04:00
parent 56722f7359
commit 96b90dc5e1
9 changed files with 65 additions and 19 deletions

View File

@@ -82,9 +82,12 @@ public:
bool hasEvent(Event *) const;
QStringList getScriptLabels(Event::Group group = Event::Group::None);
QString getScriptsFilePath() const;
QString getScriptsFilepath() const;
void openScript(const QString &label);
static QString getJsonFilepath(const QString &mapName);
QString getJsonFilepath() const { return getJsonFilepath(m_name); }
void deleteConnections();
QList<MapConnection*> getConnections() const { return m_connections; }
MapConnection* getConnection(const QString &direction) const;

View File

@@ -73,6 +73,8 @@ public:
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error = nullptr);
bool tryParseOrderedJsonFile(poryjson::Json::object *out, const QString &filepath, QString *error = nullptr);
static int getJsonLineNumber(const QString &filepath, const QString &searchText);
// Returns the 1-indexed line number for the definition of scriptLabel in the scripts file at filePath.
// Returns 0 if a definition for scriptLabel cannot be found.
static int getScriptLineNumber(const QString &filePath, const QString &scriptLabel);

View File

@@ -184,6 +184,8 @@ public:
void shouldReselectEvents();
void scaleMapView(int);
static void openInTextEditor(const QString &path, int lineNum = 0);
void openMapJson(const QString &mapName) const;
void openLayoutJson(const QString &layoutId) const;
void setCollisionGraphics();
enum ZValue {

View File

@@ -218,7 +218,7 @@ public:
static QString getScriptFileExtension(bool usePoryScript);
QString getScriptDefaultString(bool usePoryScript, QString mapName) const;
QStringList getEventScriptsFilePaths() const;
QStringList getEventScriptsFilepaths() const;
void insertGlobalScriptLabels(QStringList &scriptLabels) const;
QString getDefaultPrimaryTilesetLabel() const;

View File

@@ -142,13 +142,13 @@ void Map::invalidateScripts() {
QStringList Map::getScriptLabels(Event::Group group) {
if (!m_scriptsLoaded) {
const QString scriptsFilePath = getScriptsFilePath();
m_scriptLabels = ParseUtil::getGlobalScriptLabels(scriptsFilePath);
const QString scriptsFilepath = getScriptsFilepath();
m_scriptLabels = ParseUtil::getGlobalScriptLabels(scriptsFilepath);
m_scriptsLoaded = true;
// Track the scripts file for changes. Path may have changed, so stop tracking old files.
m_scriptFileWatcher->removePaths(m_scriptFileWatcher->files());
m_scriptFileWatcher->addPath(scriptsFilePath);
m_scriptFileWatcher->addPath(scriptsFilepath);
}
QStringList scriptLabels = m_scriptLabels;
@@ -167,7 +167,7 @@ QStringList Map::getScriptLabels(Event::Group group) {
return scriptLabels;
}
QString Map::getScriptsFilePath() const {
QString Map::getScriptsFilepath() const {
const bool usePoryscript = projectConfig.usePoryScript;
auto path = QDir::cleanPath(QString("%1/%2/%3/scripts")
.arg(projectConfig.projectDir)
@@ -180,6 +180,13 @@ QString Map::getScriptsFilePath() const {
return path;
}
QString Map::getJsonFilepath(const QString &mapName) {
return QDir::cleanPath(QString("%1/%2/%3/map.json")
.arg(projectConfig.projectDir)
.arg(projectConfig.getFilePath(ProjectFilePath::data_map_folders))
.arg(mapName));
}
void Map::resetEvents() {
m_events[Event::Group::Object].clear();
m_events[Event::Group::Warp].clear();

View File

@@ -819,14 +819,26 @@ bool ParseUtil::jsonToBool(const QJsonValue &value, bool * ok) {
return false;
}
int ParseUtil::getScriptLineNumber(const QString &filePath, const QString &scriptLabel) {
int ParseUtil::getJsonLineNumber(const QString &filepath, const QString &searchText) {
if (searchText.isEmpty())
return 0;
const QString text = readTextFile(filepath);
int index = text.indexOf(searchText);
if (index < 0)
return 0;
return text.left(index).count('\n') + 1;
}
int ParseUtil::getScriptLineNumber(const QString &filepath, const QString &scriptLabel) {
if (scriptLabel.isEmpty())
return 0;
if (filePath.endsWith(".inc") || filePath.endsWith(".s"))
return getRawScriptLineNumber(readTextFile(filePath), scriptLabel);
else if (filePath.endsWith(".pory"))
return getPoryScriptLineNumber(readTextFile(filePath), scriptLabel);
if (filepath.endsWith(".inc") || filepath.endsWith(".s"))
return getRawScriptLineNumber(readTextFile(filepath), scriptLabel);
else if (filepath.endsWith(".pory"))
return getPoryScriptLineNumber(readTextFile(filepath), scriptLabel);
return 0;
}

View File

@@ -2272,13 +2272,13 @@ void Editor::deleteSelectedEvents() {
}
void Editor::openMapScripts() const {
openInTextEditor(map->getScriptsFilePath());
openInTextEditor(map->getScriptsFilepath());
}
void Editor::openScript(const QString &scriptLabel) const {
// Find the location of scriptLabel.
QStringList scriptPaths(map->getScriptsFilePath());
scriptPaths << project->getEventScriptsFilePaths();
QStringList scriptPaths(map->getScriptsFilepath());
scriptPaths << project->getEventScriptsFilepaths();
int lineNum = 0;
QString scriptPath = scriptPaths.first();
for (const auto &path : scriptPaths) {
@@ -2292,6 +2292,16 @@ void Editor::openScript(const QString &scriptLabel) const {
openInTextEditor(scriptPath, lineNum);
}
void Editor::openMapJson(const QString &mapName) const {
openInTextEditor(Map::getJsonFilepath(mapName));
}
void Editor::openLayoutJson(const QString &layoutId) const {
QString path = QDir::cleanPath(QString("%1/%2").arg(projectConfig.projectDir).arg(projectConfig.getFilePath(ProjectFilePath::json_layouts)));
QString idField = QString("\"id\": \"%1\",").arg(layoutId);
openInTextEditor(path, ParseUtil::getJsonLineNumber(path, idField));
}
void Editor::openInTextEditor(const QString &path, int lineNum) {
QString command = porymapConfig.textEditorGotoLine;
if (command.isEmpty()) {

View File

@@ -1415,6 +1415,9 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) {
if (itemType == "map_name") {
// Right-clicking on a map.
openItemAction = menu.addAction("Open Map");
connect(menu.addAction("Open JSON file"), &QAction::triggered, [this, itemName] {
this->editor->openMapJson(itemName);
});
menu.addSeparator();
copyListNameAction = menu.addAction("Copy Map Name");
copyToolTipAction = menu.addAction("Copy Map ID");
@@ -1442,6 +1445,9 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) {
} else if (itemType == "map_layout") {
// Right-clicking on a map layout
openItemAction = menu.addAction("Open Layout");
connect(menu.addAction("Open JSON file"), &QAction::triggered, [this, itemName] {
this->editor->openLayoutJson(itemName);
});
menu.addSeparator();
copyListNameAction = menu.addAction("Copy Layout Name");
copyToolTipAction = menu.addAction("Copy Layout ID");

View File

@@ -330,7 +330,7 @@ QSet<QString> Project::getTopLevelMapFields() const {
}
bool Project::readMapJson(const QString &mapName, QJsonDocument * out) {
const QString mapFilepath = QString("%1%2/map.json").arg(projectConfig.getFilePath(ProjectFilePath::data_map_folders)).arg(mapName);
const QString mapFilepath = Map::getJsonFilepath(mapName);
watchFile(mapFilepath);
QString error;
if (!parser.tryParseJsonFile(out, mapFilepath, &error)) {
@@ -757,7 +757,11 @@ bool Project::saveMapLayouts() {
}
void Project::watchFile(const QString &filename) {
this->fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(filename));
if (!filename.startsWith(this->root)) {
this->fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(filename));
} else {
this->fileWatcher.addPath(filename);
}
}
void Project::watchFiles(const QStringList &filenames) {
@@ -1284,7 +1288,7 @@ bool Project::saveMap(Map *map, bool skipLayout) {
}
// Create map.json for map data.
QString mapFilepath = fullPath + "/map.json";
QString mapFilepath = map->getJsonFilepath();
QFile mapFile(mapFilepath);
if (!mapFile.open(QIODevice::WriteOnly)) {
logError(QString("Could not open '%1' for writing: %2").arg(mapFilepath).arg(mapFile.errorString()));
@@ -2930,7 +2934,7 @@ bool Project::readEventScriptLabels() {
this->globalScriptLabels.clear();
if (porymapConfig.loadAllEventScripts) {
for (const auto &filePath : getEventScriptsFilePaths())
for (const auto &filePath : getEventScriptsFilepaths())
this->globalScriptLabels << ParseUtil::getGlobalScriptLabels(filePath);
this->globalScriptLabels.sort(Qt::CaseInsensitive);
@@ -2973,7 +2977,7 @@ QString Project::getScriptDefaultString(bool usePoryScript, QString mapName) con
return QString("%1_MapScripts::\n\t.byte 0\n").arg(mapName);
}
QStringList Project::getEventScriptsFilePaths() const {
QStringList Project::getEventScriptsFilepaths() const {
QStringList filePaths(QDir::cleanPath(root + "/" + projectConfig.getFilePath(ProjectFilePath::data_event_scripts)));
const QString scriptsDir = QDir::cleanPath(root + "/" + projectConfig.getFilePath(ProjectFilePath::data_scripts_folders));
const QString mapsDir = QDir::cleanPath(root + "/" + projectConfig.getFilePath(ProjectFilePath::data_map_folders));