Add utility.cpp, fix bug when map/layout name is just underscores

This commit is contained in:
GriffinR 2025-02-22 14:54:44 -05:00
parent 67c3a4befd
commit 1b510b6a6e
13 changed files with 82 additions and 57 deletions

View File

@ -45,7 +45,8 @@ public:
void setConstantName(const QString &constantName) { m_constantName = constantName; }
QString constantName() const { return m_constantName; }
static QString mapConstantFromName(QString mapName, bool includePrefix = true);
static QString mapConstantFromName(const QString &name);
QString expectedConstantName() const { return Map::mapConstantFromName(m_name); }
void setLayout(Layout *layout);
Layout* layout() const { return m_layout; }

View File

@ -20,9 +20,7 @@ public:
Layout() {}
Layout(const Layout &other);
static QString layoutConstantFromName(QString mapName);
static QString defaultSuffix();
static QString layoutConstantFromName(const QString &name);
bool loaded = false;

13
include/core/utility.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#ifndef UTILITY_H
#define UTILITY_H
#include <QString>
namespace Util {
void numericalModeSort(QStringList &list);
int roundUp(int numToRound, int multiple);
QString toDefineCase(QString input);
}
#endif // UTILITY_H

View File

@ -248,8 +248,6 @@ public:
static QString getEmptyMapsecName();
static QString getMapGroupPrefix();
static void numericalModeSort(QStringList &list);
private:
QMap<QString, QString> mapSectionDisplayNames;
QMap<QString, qint64> modifiedFileTimestamps;

View File

@ -51,6 +51,7 @@ SOURCES += src/core/advancemapparser.cpp \
src/core/parseutil.cpp \
src/core/tile.cpp \
src/core/tileset.cpp \
src/core/utility.cpp \
src/core/validator.cpp \
src/core/regionmap.cpp \
src/core/wildmoninfo.cpp \
@ -162,6 +163,7 @@ HEADERS += include/core/advancemapparser.h \
include/core/parseutil.h \
include/core/tile.h \
include/core/tileset.h \
include/core/utility.h \
include/core/validator.h \
include/core/regionmap.h \
include/core/wildmoninfo.h \

View File

@ -2,7 +2,7 @@
#include "map.h"
#include "imageproviders.h"
#include "scripting.h"
#include "utility.h"
#include "editcommands.h"
#include <QTime>
@ -56,14 +56,9 @@ void Map::setLayout(Layout *layout) {
}
}
QString Map::mapConstantFromName(QString mapName, bool includePrefix) {
// Transform map names of the form 'GraniteCave_B1F` into map constants like 'MAP_GRANITE_CAVE_B1F'.
static const QRegularExpression caseChange("([a-z])([A-Z])");
QString nameWithUnderscores = mapName.replace(caseChange, "\\1_\\2");
const QString prefix = includePrefix ? projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) : "";
QString withMapAndUppercase = prefix + nameWithUnderscores.toUpper();
static const QRegularExpression underscores("_+");
return withMapAndUppercase.replace(underscores, "_");
// We don't enforce this for existing maps, but for creating new maps we need to formulaically generate a new MAP_NAME ID.
QString Map::mapConstantFromName(const QString &name) {
return projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) + Util::toDefineCase(name);
}
int Map::getWidth() const {

View File

@ -4,6 +4,7 @@
#include "scripting.h"
#include "imageproviders.h"
#include "utility.h"
Layout::Layout(const Layout &other) : Layout() {
copyFrom(&other);
@ -32,13 +33,9 @@ void Layout::copyFrom(const Layout *other) {
this->border = other->border;
}
QString Layout::layoutConstantFromName(QString mapName) {
// Transform map names of the form 'GraniteCave_B1F` into layout constants like 'LAYOUT_GRANITE_CAVE_B1F'.
static const QRegularExpression caseChange("([a-z])([A-Z])");
QString nameWithUnderscores = mapName.replace(caseChange, "\\1_\\2");
QString withMapAndUppercase = "LAYOUT_" + nameWithUnderscores.toUpper();
static const QRegularExpression underscores("_+");
return withMapAndUppercase.replace(underscores, "_");
QString Layout::layoutConstantFromName(const QString &name) {
// TODO: Expose "LAYOUT_" to config
return "LAYOUT_" + Util::toDefineCase(name);
}
Layout::Settings Layout::settings() const {

40
src/core/utility.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "utility.h"
#include <QCollator>
#include <QRegularExpression>
// Sometimes we want to sort names alphabetically to make them easier to find in large combo box lists.
// QStringList::sort (as of writing) can only sort numbers in lexical order, which has an undesirable
// effect (e.g. MAPSEC_ROUTE_10 comes after MAPSEC_ROUTE_1, rather than MAPSEC_ROUTE_9).
// We can use QCollator to sort these lists with better handling for numbers.
void Util::numericalModeSort(QStringList &list) {
static QCollator collator;
collator.setNumericMode(true);
std::sort(list.begin(), list.end(), collator);
}
int Util::roundUp(int numToRound, int multiple) {
if (multiple <= 0)
return numToRound;
int remainder = abs(numToRound) % multiple;
if (remainder == 0)
return numToRound;
if (numToRound < 0)
return -(abs(numToRound) - remainder);
else
return numToRound + multiple - remainder;
}
// Ex: input 'GraniteCave_B1F' returns 'GRANITE_CAVE_B1F'.
QString Util::toDefineCase(QString input) {
static const QRegularExpression re_CaseChange("([a-z])([A-Z])");
input.replace(re_CaseChange, "\\1_\\2");
// Remove sequential underscores
static const QRegularExpression re_Underscores("_+");
input.replace(re_Underscores, "_");
return input.toUpper();
}

View File

@ -10,6 +10,7 @@
#include "filedialog.h"
#include "validator.h"
#include "orderedjson.h"
#include "utility.h"
#include <QDir>
#include <QJsonArray>
@ -349,7 +350,7 @@ Map *Project::createNewMap(const Project::NewMapSettings &settings, const Map* t
map->setNeedsHealLocation(settings.canFlyTo);
// Generate a unique MAP constant.
map->setConstantName(toUniqueIdentifier(Map::mapConstantFromName(map->name())));
map->setConstantName(toUniqueIdentifier(map->expectedConstantName()));
Layout *layout = this->mapLayouts.value(settings.layout.id);
if (!layout) {
@ -2074,8 +2075,8 @@ bool Project::readTilesetLabels() {
}
}
numericalModeSort(this->primaryTilesetLabels);
numericalModeSort(this->secondaryTilesetLabels);
Util::numericalModeSort(this->primaryTilesetLabels);
Util::numericalModeSort(this->secondaryTilesetLabels);
bool success = true;
if (this->secondaryTilesetLabels.isEmpty()) {
@ -2348,7 +2349,7 @@ bool Project::readRegionMapSections() {
if (!this->mapSectionIdNames.contains(defaultName)) {
this->mapSectionIdNames.append(defaultName);
}
numericalModeSort(this->mapSectionIdNames);
Util::numericalModeSort(this->mapSectionIdNames);
return true;
}
@ -2372,7 +2373,7 @@ void Project::addNewMapsec(const QString &idName) {
}
this->mapSectionIdNames.append(idName);
numericalModeSort(this->mapSectionIdNames);
Util::numericalModeSort(this->mapSectionIdNames);
this->hasUnsavedDataChanges = true;
@ -2596,7 +2597,7 @@ bool Project::readSongNames() {
// Song names don't have a very useful order (esp. if we include SE_* values), so sort them alphabetically.
// The default song should be the first in the list, not the first alphabetically, so save that before sorting.
this->defaultSong = this->songNames.value(0, "0");
numericalModeSort(this->songNames);
Util::numericalModeSort(this->songNames);
return true;
}
@ -3058,14 +3059,3 @@ bool Project::hasUnsavedChanges() {
}
return false;
}
// TODO: This belongs in a more general utility file, once we have one.
// Sometimes we want to sort names alphabetically to make them easier to find in large combo box lists.
// QStringList::sort (as of writing) can only sort numbers in lexical order, which has an undesirable
// effect (e.g. MAPSEC_ROUTE_10 comes after MAPSEC_ROUTE_1, rather than MAPSEC_ROUTE_9).
// We can use QCollator to sort these lists with better handling for numbers.
void Project::numericalModeSort(QStringList &list) {
QCollator collator;
collator.setNumericMode(true);
std::sort(list.begin(), list.end(), collator);
}

View File

@ -3,6 +3,7 @@
#include <QMessageBox>
#include "movablerect.h"
#include "utility.h"
MovableRect::MovableRect(bool *enabled, int width, int height, QRgb color)
: QGraphicsRectItem(0, 0, width, height)
@ -22,10 +23,6 @@ void MovableRect::updateLocation(int x, int y) {
************************************************************************
******************************************************************************/
int roundUp(int numToRound, int multiple) {
return (numToRound + multiple - 1) & -multiple;
}
ResizableRect::ResizableRect(QObject *parent, bool *enabled, int width, int height, QRgb color)
: QObject(parent),
MovableRect(enabled, width * 16, height * 16, color)
@ -117,8 +114,8 @@ void ResizableRect::mousePressEvent(QGraphicsSceneMouseEvent *event) {
}
void ResizableRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
int dx = roundUp(event->scenePos().x() - this->clickedPos.x(), 16);
int dy = roundUp(event->scenePos().y() - this->clickedPos.y(), 16);
int dx = Util::roundUp(event->scenePos().x() - this->clickedPos.x(), 16);
int dy = Util::roundUp(event->scenePos().y() - this->clickedPos.y(), 16);
QRect resizedRect = this->clickedRect;

View File

@ -3,6 +3,7 @@
#include "noscrollcombobox.h"
#include "prefab.h"
#include "filedialog.h"
#include "utility.h"
#include <QAbstractButton>
#include <QFormLayout>
@ -293,7 +294,7 @@ QStringList ProjectSettingsEditor::getWarpBehaviorsList() {
void ProjectSettingsEditor::setWarpBehaviorsList(QStringList list) {
list.removeDuplicates();
Project::numericalModeSort(list);
Util::numericalModeSort(list);
ui->textEdit_WarpBehaviors->setText(list.join("\n"));
}

View File

@ -2,12 +2,10 @@
#include "editor.h"
#include "movablerect.h"
#include "config.h"
#include "utility.h"
#include "ui_resizelayoutpopup.h"
// TODO: put this in a util file or something
extern int roundUp(int, int);
CheckeredBgScene::CheckeredBgScene(QObject *parent) : QGraphicsScene(parent) { }
void CheckeredBgScene::drawBackground(QPainter *painter, const QRectF &rect) {
@ -62,7 +60,7 @@ void BoundedPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
QVariant BoundedPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value) {
if (change == ItemPositionChange && scene()) {
QPointF newPos = value.toPointF();
return QPointF(roundUp(newPos.x(), 16), roundUp(newPos.y(), 16));
return QPointF(Util::roundUp(newPos.x(), 16), Util::roundUp(newPos.y(), 16));
}
else
return QGraphicsItem::itemChange(change, value);

View File

@ -2,6 +2,7 @@
#include "wildmonchart.h"
#include "ui_wildmonchart.h"
#include "config.h"
#include "utility.h"
static const QString baseWindowTitle = QString("Wild Pokémon Summary Charts");
@ -367,13 +368,7 @@ QChart* WildMonChart::createLevelDistributionChart() {
series->attachAxis(axisY);
// We round the y-axis max up to a multiple of 5.
auto roundUp = [](int num, int multiple) {
auto remainder = num % multiple;
if (remainder == 0)
return num;
return num + multiple - remainder;
};
axisY->setMax(roundUp(qCeil(axisY->max()), 5));
axisY->setMax(Util::roundUp(qCeil(axisY->max()), 5));
return chart;
}