diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5e78fe5e..5d489b17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -103,6 +103,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
- Fix exporting a timelapse sometimes altering the state of the current map's edit history.
- Stop sliders in the Palette Editor from creating a bunch of edit history when used.
- Fix scrolling on some containers locking up when the mouse stops over a spin box or combo box.
+- Fix the selection index for some combo boxes differing from their displayed text.
- Fix some file dialogs returning to an incorrect window when closed.
- Fix bug where reloading a layout would overwrite all unsaved changes.
- Fix bug where layout json and blockdata could be saved separately leading to inconsistent data.
diff --git a/forms/aboutporymap.ui b/forms/aboutporymap.ui
index 7a211e0a..fc777020 100644
--- a/forms/aboutporymap.ui
+++ b/forms/aboutporymap.ui
@@ -6,7 +6,7 @@
0
0
- 383
+ 388
121
@@ -53,6 +53,9 @@
Qt::AlignmentFlag::AlignCenter
+
+ Qt::TextInteractionFlag::TextSelectableByMouse
+
-
diff --git a/forms/eventpropertiesframe.ui b/forms/eventpropertiesframe.ui
deleted file mode 100644
index 4629438f..00000000
--- a/forms/eventpropertiesframe.ui
+++ /dev/null
@@ -1,319 +0,0 @@
-
-
- EventPropertiesFrame
-
-
-
- 0
- 0
- 284
- 146
-
-
-
-
- 0
- 0
-
-
-
-
- 284
- 90
-
-
-
- Frame
-
-
- Qt::LeftToRight
-
-
- QFrame::Box
-
-
- QFrame::Raised
-
-
- 1
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 64
- 64
-
-
-
- QFrame::Box
-
-
- QFrame::Sunken
-
-
-
-
-
- false
-
-
- Qt::AlignCenter
-
-
- -1
-
-
-
- -
-
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
- Qt::StrongFocus
-
-
- The index of the event currently being inspected.
-
-
- 255
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Id
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- X
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- <html><head/><body><p>The X coordinate of this object.</p></body></html>
-
-
- -32768
-
-
- 32767
-
-
-
-
-
- -
-
-
-
-
-
- Y
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- <html><head/><body><p>The Y coordinate of this object.</p></body></html>
-
-
- -32768
-
-
- 32767
-
-
-
-
-
- -
-
-
-
-
-
- Z
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- <html><head/><body><p>The elevation of this object.</p></body></html>
-
-
- 15
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- QFormLayout::WrapLongRows
-
-
- 9
-
-
- 0
-
-
- 0
-
-
-
-
-
- Sprite
-
-
- comboBox_sprite
-
-
-
- -
-
-
- true
-
-
- Qt::StrongFocus
-
-
- <html><head/><body><p>The sprite graphics to use for this object.</p></body></html>
-
-
- true
-
-
-
-
-
- 25
-
-
- QComboBox::AdjustToContentsOnFirstShow
-
-
-
-
-
-
-
-
-
-
- NoScrollComboBox
- QComboBox
-
-
-
- NoScrollSpinBox
- QSpinBox
-
-
-
-
- spinBox_x
- spinBox_y
- spinBox_z
- comboBox_sprite
-
-
-
-
diff --git a/forms/loadingscreen.ui b/forms/loadingscreen.ui
index d6f52430..4ed06b9f 100644
--- a/forms/loadingscreen.ui
+++ b/forms/loadingscreen.ui
@@ -3,7 +3,7 @@
LoadingScreen
- Qt::ApplicationModal
+ Qt::WindowModality::ApplicationModal
@@ -17,7 +17,7 @@
BusyCursor
- Qt::NoContextMenu
+ Qt::ContextMenuPolicy::NoContextMenu
Form
@@ -35,7 +35,7 @@
porymap
- Qt::AlignCenter
+ Qt::AlignmentFlag::AlignCenter
@@ -50,14 +50,14 @@
Version X.x.x
- Qt::AlignCenter
+ Qt::AlignmentFlag::AlignCenter
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -70,16 +70,16 @@
-
- QFrame::NoFrame
+ QFrame::Shape::NoFrame
- QFrame::Raised
+ QFrame::Shadow::Raised
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -105,7 +105,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -121,7 +121,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -134,23 +134,16 @@
-
- QFrame::NoFrame
+ QFrame::Shape::NoFrame
- QFrame::Plain
+ QFrame::Shadow::Plain
-
-
-
-
- Loading.....
-
-
-
-
- TextLabel
+ Loading....
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui
index bf0d2608..c75c8328 100644
--- a/forms/mainwindow.ui
+++ b/forms/mainwindow.ui
@@ -2733,7 +2733,10 @@
-
-
+
+
+ false
+
QComboBox::SizeAdjustPolicy::AdjustToContents
diff --git a/forms/mapheaderform.ui b/forms/mapheaderform.ui
index 08552e2c..d4fc36f3 100644
--- a/forms/mapheaderform.ui
+++ b/forms/mapheaderform.ui
@@ -10,6 +10,9 @@
380
+
+ Qt::FocusPolicy::ClickFocus
+
Form
diff --git a/forms/wildmonchart.ui b/forms/wildmonchart.ui
index 8d6668e4..05c0ba44 100644
--- a/forms/wildmonchart.ui
+++ b/forms/wildmonchart.ui
@@ -197,7 +197,7 @@
-
-
+
true
@@ -237,6 +237,11 @@
QGraphicsView
+
+ NoScrollComboBox
+ QComboBox
+
+
diff --git a/include/core/events.h b/include/core/events.h
index 9da9b531..76a58dcf 100644
--- a/include/core/events.h
+++ b/include/core/events.h
@@ -34,15 +34,6 @@ class HiddenItemEvent;
class SecretBaseEvent;
class HealLocationEvent;
-class EventVisitor {
-public:
- virtual void nothing() { }
- virtual void visitObject(ObjectEvent *) = 0;
- virtual void visitTrigger(TriggerEvent *) = 0;
- virtual void visitSign(SignEvent *) = 0;
-};
-
-
///
/// Event base class -- purely virtual
///
@@ -121,8 +112,6 @@ public:
void modify();
- virtual void accept(EventVisitor *) { }
-
void setX(int newX) { this->x = newX; }
void setY(int newY) { this->y = newY; }
void setZ(int newZ) { this->elevation = newZ; }
@@ -150,6 +139,8 @@ public:
virtual QSet getExpectedFields() = 0;
+ virtual QStringList getScripts() const { return QStringList(); }
+
QJsonObject getCustomAttributes() const { return this->customAttributes; }
void setCustomAttributes(const QJsonObject &newCustomAttributes) { this->customAttributes = newCustomAttributes; }
@@ -222,8 +213,6 @@ public:
virtual Event *duplicate() const override;
- virtual void accept(EventVisitor *visitor) override { visitor->visitObject(this); }
-
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
@@ -233,6 +222,8 @@ public:
virtual QSet getExpectedFields() override;
+ virtual QStringList getScripts() const override { return {getScript()}; }
+
virtual QPixmap loadPixmap(Project *project) override;
void setGfx(QString newGfx) { this->gfx = newGfx; }
@@ -392,8 +383,6 @@ public:
virtual Event *duplicate() const override;
- virtual void accept(EventVisitor *visitor) override { visitor->visitTrigger(this); }
-
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
@@ -403,6 +392,8 @@ public:
virtual QSet getExpectedFields() override;
+ virtual QStringList getScripts() const override { return {getScriptLabel()}; }
+
void setScriptVar(QString newScriptVar) { this->scriptVar = newScriptVar; }
QString getScriptVar() const { return this->scriptVar; }
@@ -490,8 +481,6 @@ public:
virtual Event *duplicate() const override;
- virtual void accept(EventVisitor *visitor) override { visitor->visitSign(this); }
-
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
@@ -501,6 +490,8 @@ public:
virtual QSet getExpectedFields() override;
+ virtual QStringList getScripts() const override { return {getScriptLabel()}; }
+
void setFacingDirection(QString newFacingDirection) { this->facingDirection = newFacingDirection; }
QString getFacingDirection() const { return this->facingDirection; }
@@ -633,21 +624,4 @@ inline uint qHash(const Event::Group &key, uint seed = 0) {
return qHash(static_cast(key), seed);
}
-
-///
-/// Keeps track of scripts
-///
-class ScriptTracker : public EventVisitor {
-public:
- virtual void visitObject(ObjectEvent *object) override { this->scripts << object->getScript(); };
- virtual void visitTrigger(TriggerEvent *trigger) override { this->scripts << trigger->getScriptLabel(); };
- virtual void visitSign(SignEvent *sign) override { this->scripts << sign->getScriptLabel(); };
-
- QStringList getScripts() const { return this->scripts; }
-
-private:
- QStringList scripts;
-};
-
-
#endif // EVENTS_H
diff --git a/include/core/map.h b/include/core/map.h
index 84791fa3..2ba172ce 100644
--- a/include/core/map.h
+++ b/include/core/map.h
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#define DEFAULT_BORDER_WIDTH 2
@@ -56,7 +57,7 @@ public:
MapHeader* header() const { return m_header; }
void setSharedEventsMap(const QString &sharedEventsMap) { m_sharedEventsMap = sharedEventsMap; }
- void setSharedScriptsMap(const QString &sharedScriptsMap) { m_sharedScriptsMap = sharedScriptsMap; }
+ void setSharedScriptsMap(const QString &sharedScriptsMap);
QString sharedEventsMap() const { return m_sharedEventsMap; }
QString sharedScriptsMap() const { return m_sharedScriptsMap; }
@@ -75,14 +76,15 @@ public:
Event* getEvent(Event::Group group, const QString &idName) const;
QStringList getEventIdNames(Event::Group group) const;
int getNumEvents(Event::Group group = Event::Group::None) const;
- QStringList getScriptLabels(Event::Group group = Event::Group::None);
- QString getScriptsFilePath() const;
- void openScript(QString label);
void removeEvent(Event *);
void addEvent(Event *);
int getIndexOfEvent(Event *) const;
bool hasEvent(Event *) const;
+ QStringList getScriptLabels(Event::Group group = Event::Group::None);
+ QString getScriptsFilePath() const;
+ void openScript(const QString &label);
+
void deleteConnections();
QList getConnections() const { return m_connections; }
MapConnection* getConnection(const QString &direction) const;
@@ -108,7 +110,7 @@ private:
QString m_sharedEventsMap = "";
QString m_sharedScriptsMap = "";
- QStringList m_scriptsFileLabels;
+ QStringList m_scriptLabels;
QJsonObject m_customAttributes;
MapHeader *m_header = nullptr;
@@ -131,10 +133,14 @@ private:
QList m_connections;
QSet m_ownedConnections;
- QUndoStack *m_editHistory = nullptr;
+ QPointer m_editHistory;
+ QPointer m_scriptFileWatcher;
+
+ void invalidateScripts();
signals:
void modified();
+ void scriptsModified();
void mapDimensionsChanged(const QSize &size);
void openScriptRequested(QString label);
void connectionAdded(MapConnection*);
diff --git a/include/core/parseutil.h b/include/core/parseutil.h
index aae86a88..2edb9f78 100644
--- a/include/core/parseutil.h
+++ b/include/core/parseutil.h
@@ -43,8 +43,13 @@ class ParseUtil
{
public:
ParseUtil();
+
void setRoot(const QString &dir) { this->root = dir; }
+ void setUpdatesSplashScreen(bool updates) { this->updatesSplashScreen = updates; }
+
static QString readTextFile(const QString &path, QString *error = nullptr);
+ QString loadTextFile(const QString &path, QString *error = nullptr);
+
bool cacheFile(const QString &path, QString *error = nullptr);
void clearFileCache() { this->fileCache.clear(); }
static int textFileLineCount(const QString &path);
@@ -105,6 +110,8 @@ private:
QHash globalDefineValues;
QHash globalDefineExpressions;
+ bool updatesSplashScreen = false;
+
int evaluateDefine(const QString &identifier, bool *ok = nullptr);
int evaluateExpression(const QString &expression);
QList tokenizeExpression(QString expression);
@@ -114,6 +121,7 @@ private:
void recordErrors(const QStringList &errors);
void logRecordedErrors();
QString createErrorMessage(const QString &message, const QString &expression);
+ void updateSplashScreen(QString path);
struct ParsedDefines {
QHash expressions; // Map of all define names encountered to their expressions
@@ -123,7 +131,6 @@ private:
QHash evaluateCDefines(const QString &filename, const QSet &filterList, bool useRegex, QString *error);
bool defineNameMatchesFilter(const QString &name, const QSet &filterList) const;
bool defineNameMatchesFilter(const QString &name, const QSet &filterList) const;
- QString loadTextFile(const QString &path, QString *error = nullptr);
QString pathWithRoot(const QString &path);
static const QRegularExpression re_incScriptLabel;
diff --git a/include/core/tileset.h b/include/core/tileset.h
index a05afdc3..abb31ab1 100644
--- a/include/core/tileset.h
+++ b/include/core/tileset.h
@@ -67,9 +67,9 @@ public:
bool saveTilesImage();
bool savePalettes();
- bool appendToHeaders(QString root, QString friendlyName, bool usingAsm);
- bool appendToGraphics(QString root, QString friendlyName, bool usingAsm);
- bool appendToMetatiles(QString root, QString friendlyName, bool usingAsm);
+ bool appendToHeaders(const QString &filepath, const QString &friendlyName, bool usingAsm);
+ bool appendToGraphics(const QString &filepath, const QString &friendlyName, bool usingAsm);
+ bool appendToMetatiles(const QString &filepath, const QString &friendlyName, bool usingAsm);
void setTilesImage(const QImage &image);
diff --git a/include/project.h b/include/project.h
index 99c7d7b7..6f981a85 100644
--- a/include/project.h
+++ b/include/project.h
@@ -309,7 +309,10 @@ private:
void setNewLayoutBlockdata(Layout *layout);
void setNewLayoutBorder(Layout *layout);
- void ignoreWatchedFileTemporarily(QString filepath);
+ void watchFile(const QString &filename);
+ void watchFiles(const QStringList &filenames);
+ void ignoreWatchedFileTemporarily(const QString &filepath);
+ void ignoreWatchedFilesTemporarily(const QStringList &filepaths);
void recordFileChange(const QString &filepath);
void resetFileCache();
diff --git a/include/ui/divingmappixmapitem.h b/include/ui/divingmappixmapitem.h
index 7eceba07..0a4a32c1 100644
--- a/include/ui/divingmappixmapitem.h
+++ b/include/ui/divingmappixmapitem.h
@@ -2,6 +2,7 @@
#define DIVINGMAPPIXMAPITEM_H
#include "mapconnection.h"
+#include "noscrollcombobox.h"
#include
#include
@@ -10,7 +11,7 @@
class DivingMapPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
- DivingMapPixmapItem(MapConnection *connection, QComboBox *combo);
+ DivingMapPixmapItem(MapConnection *connection, NoScrollComboBox *combo);
~DivingMapPixmapItem();
MapConnection* connection() const { return m_connection; }
@@ -18,7 +19,7 @@ public:
private:
QPointer m_connection;
- QPointer m_combo;
+ QPointer m_combo;
void setComboText(const QString &text);
static QPixmap getBasePixmap(MapConnection* connection);
diff --git a/include/ui/eventframes.h b/include/ui/eventframes.h
index 09eae50b..3858e54e 100644
--- a/include/ui/eventframes.h
+++ b/include/ui/eventframes.h
@@ -56,9 +56,11 @@ protected:
bool populated = false;
bool initialized = false;
bool connected = false;
+ QPointer project;
void populateDropdown(NoScrollComboBox * combo, const QStringList &items);
void populateScriptDropdown(NoScrollComboBox * combo, Project * project);
+ void populateMapNameDropdown(NoScrollComboBox * combo, Project * project);
void populateIdNameDropdown(NoScrollComboBox * combo, Project * project, const QString &mapName, Event::Group group);
private:
diff --git a/include/ui/loadingscreen.h b/include/ui/loadingscreen.h
index df55b01c..ff88e87c 100644
--- a/include/ui/loadingscreen.h
+++ b/include/ui/loadingscreen.h
@@ -18,8 +18,10 @@ public:
explicit PorymapLoadingScreen(QWidget *parent = nullptr);
~PorymapLoadingScreen();
- void setPixmap(QPixmap pixmap);
- void showMessage(QString text);
+ void setPixmap(const QPixmap &pixmap);
+ void showMessage(const QString &text);
+ void showMessage(const QString &prefix, const QString &text);
+ void showLoadingMessage(const QString &text);
void start();
void stop ();
diff --git a/include/ui/mapheaderform.h b/include/ui/mapheaderform.h
index 4f3dc775..fb4f7aa9 100644
--- a/include/ui/mapheaderform.h
+++ b/include/ui/mapheaderform.h
@@ -12,6 +12,7 @@
#include "mapheader.h"
#include "project.h"
+#include "noscrollcombobox.h"
namespace Ui {
class MapHeaderForm;
@@ -64,7 +65,7 @@ private:
QPointer m_project = nullptr;
bool m_allowProjectChanges = true;
- void setText(QComboBox *combo, const QString &text) const;
+ void setText(NoScrollComboBox *combo, const QString &text) const;
void setText(QLineEdit *lineEdit, const QString &text) const;
void setLocations(const QStringList &locations);
void updateLocationName();
diff --git a/src/core/events.cpp b/src/core/events.cpp
index 22315211..ce376c44 100644
--- a/src/core/events.cpp
+++ b/src/core/events.cpp
@@ -114,7 +114,7 @@ QString Event::typeToString(Event::Type type) {
}
QPixmap Event::loadPixmap(Project *project) {
- this->pixmap = project->getEventPixmap(this->getEventGroup());
+ this->pixmap = project ? project->getEventPixmap(this->getEventGroup()) : QPixmap();
this->usesDefaultPixmap = true;
return this->pixmap;
}
@@ -226,7 +226,7 @@ QSet ObjectEvent::getExpectedFields() {
}
QPixmap ObjectEvent::loadPixmap(Project *project) {
- this->pixmap = project->getEventPixmap(this->gfx, this->movement);
+ this->pixmap = project ? project->getEventPixmap(this->gfx, this->movement) : QPixmap();
if (!this->pixmap.isNull()) {
this->usesDefaultPixmap = false;
return this->pixmap;
@@ -316,7 +316,7 @@ QSet CloneObjectEvent::getExpectedFields() {
QPixmap CloneObjectEvent::loadPixmap(Project *project) {
// Try to get the targeted object to clone
- Map *clonedMap = project->loadMap(this->targetMap);
+ Map *clonedMap = project ? project->loadMap(this->targetMap) : nullptr;
Event *clonedEvent = clonedMap ? clonedMap->getEvent(Event::Group::Object, this->targetID) : nullptr;
if (clonedEvent && clonedEvent->getEventType() == Event::Type::Object) {
@@ -324,10 +324,13 @@ QPixmap CloneObjectEvent::loadPixmap(Project *project) {
ObjectEvent *clonedObject = dynamic_cast(clonedEvent);
this->gfx = clonedObject->getGfx();
this->movement = clonedObject->getMovement();
- } else {
+ } else if (project) {
// Invalid object specified, use default graphics data (as would be shown in-game)
this->gfx = project->gfxDefines.key(0, "0");
this->movement = project->movementTypes.value(0, "0");
+ } else {
+ this->gfx = "0";
+ this->movement = "0";
}
return ObjectEvent::loadPixmap(project);
}
diff --git a/src/core/map.cpp b/src/core/map.cpp
index 3cd087e1..c1905f0a 100644
--- a/src/core/map.cpp
+++ b/src/core/map.cpp
@@ -14,6 +14,10 @@
Map::Map(QObject *parent) : QObject(parent)
{
m_editHistory = new QUndoStack(this);
+
+ m_scriptFileWatcher = new QFileSystemWatcher(this);
+ connect(m_scriptFileWatcher, &QFileSystemWatcher::fileChanged, this, &Map::invalidateScripts);
+
resetEvents();
m_header = new MapHeader(this);
@@ -120,35 +124,40 @@ QPixmap Map::renderConnection(const QString &direction, Layout * fromLayout) {
return connectionPixmap.copy(bounds.x() * 16, bounds.y() * 16, bounds.width() * 16, bounds.height() * 16);
}
-void Map::openScript(QString label) {
+void Map::openScript(const QString &label) {
emit openScriptRequested(label);
}
+void Map::setSharedScriptsMap(const QString &sharedScriptsMap) {
+ if (m_sharedScriptsMap == sharedScriptsMap)
+ return;
+ m_sharedScriptsMap = sharedScriptsMap;
+ invalidateScripts();
+}
+
+void Map::invalidateScripts() {
+ m_scriptsLoaded = false;
+ emit scriptsModified();
+}
+
QStringList Map::getScriptLabels(Event::Group group) {
if (!m_scriptsLoaded) {
- m_scriptsFileLabels = ParseUtil::getGlobalScriptLabels(getScriptsFilePath());
+ 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);
}
- QStringList scriptLabels;
+ QStringList scriptLabels = m_scriptLabels;
- // Get script labels currently in-use by the map's events
- if (group == Event::Group::None) {
- ScriptTracker scriptTracker;
- for (const auto &event : getEvents()) {
- event->accept(&scriptTracker);
- }
- scriptLabels = scriptTracker.getScripts();
- } else {
- ScriptTracker scriptTracker;
- for (const auto &event : m_events.value(group)) {
- event->accept(&scriptTracker);
- }
- scriptLabels = scriptTracker.getScripts();
+ // Add script labels currently in-use by the map's events
+ for (const auto &event : getEvents(group)) {
+ scriptLabels.append(event->getScripts());
}
- // Add labels from the map's scripts file
- scriptLabels.append(m_scriptsFileLabels);
scriptLabels.sort(Qt::CaseInsensitive);
scriptLabels.removeAll("");
scriptLabels.removeAll("0");
diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp
index cba8c223..80252c13 100644
--- a/src/core/parseutil.cpp
+++ b/src/core/parseutil.cpp
@@ -56,9 +56,17 @@ QString ParseUtil::createErrorMessage(const QString &message, const QString &exp
return QString("%1:%2:%3: %4").arg(this->file).arg(lineNum).arg(colNum).arg(message);
}
+void ParseUtil::updateSplashScreen(QString path) {
+ if (!this->updatesSplashScreen)
+ return;
+
+ if (path.startsWith(this->root)) {
+ path.remove(0, this->root.length());
+ }
+ porysplash->showLoadingMessage(path);
+}
+
QString ParseUtil::readTextFile(const QString &path, QString *error) {
- // splash screen message
- porysplash->showMessage(path);
QFile file(path);
if (!file.open(QIODevice::ReadOnly)) {
if (error) *error = file.errorString();
@@ -80,6 +88,8 @@ QString ParseUtil::readTextFile(const QString &path, QString *error) {
// Note that this doesn't insert any parsed files into the file cache, and we don't
// want it to (we read a lot of files only once, storing them all is a waste of memory).
QString ParseUtil::loadTextFile(const QString &path, QString *error) {
+ updateSplashScreen(path);
+
auto it = this->fileCache.constFind(path);
if (it != this->fileCache.constEnd()) {
// Load text file from cache
@@ -89,6 +99,8 @@ QString ParseUtil::loadTextFile(const QString &path, QString *error) {
}
bool ParseUtil::cacheFile(const QString &path, QString *error) {
+ updateSplashScreen(path);
+
this->fileCache.insert(path, readTextFile(pathWithRoot(path), error));
return !error || error->isEmpty();
}
@@ -732,6 +744,8 @@ QStringList ParseUtil::getLabelValues(const QList &list, const QStr
}
bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error) {
+ updateSplashScreen(filepath);
+
QFile file(pathWithRoot(filepath));
if (!file.open(QIODevice::ReadOnly)) {
if (error) *error = file.errorString();
diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp
index 0ad43d1a..dc3bbd65 100644
--- a/src/core/tileset.cpp
+++ b/src/core/tileset.cpp
@@ -249,12 +249,10 @@ QList Tileset::getPalette(int paletteId, Tileset *primaryTileset, Tileset
return paletteTable;
}
-bool Tileset::appendToHeaders(QString root, QString friendlyName, bool usingAsm) {
- QString headersFile = root + "/" + (usingAsm ? projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm)
- : projectConfig.getFilePath(ProjectFilePath::tilesets_headers));
- QFile file(headersFile);
+bool Tileset::appendToHeaders(const QString &filepath, const QString &friendlyName, bool usingAsm) {
+ QFile file(filepath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) {
- logError(QString("Could not write to file \"%1\"").arg(headersFile));
+ logError(QString("Could not write to file \"%1\"").arg(filepath));
return false;
}
QString isSecondaryStr = this->is_secondary ? "TRUE" : "FALSE";
@@ -294,12 +292,10 @@ bool Tileset::appendToHeaders(QString root, QString friendlyName, bool usingAsm)
return true;
}
-bool Tileset::appendToGraphics(QString root, QString friendlyName, bool usingAsm) {
- QString graphicsFile = root + "/" + (usingAsm ? projectConfig.getFilePath(ProjectFilePath::tilesets_graphics_asm)
- : projectConfig.getFilePath(ProjectFilePath::tilesets_graphics));
- QFile file(graphicsFile);
+bool Tileset::appendToGraphics(const QString &filepath, const QString &friendlyName, bool usingAsm) {
+ QFile file(filepath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) {
- logError(QString("Could not write to file \"%1\"").arg(graphicsFile));
+ logError(QString("Could not write to file \"%1\"").arg(filepath));
return false;
}
@@ -332,12 +328,10 @@ bool Tileset::appendToGraphics(QString root, QString friendlyName, bool usingAsm
return true;
}
-bool Tileset::appendToMetatiles(QString root, QString friendlyName, bool usingAsm) {
- QString metatileFile = root + "/" + (usingAsm ? projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles_asm)
- : projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles));
- QFile file(metatileFile);
+bool Tileset::appendToMetatiles(const QString &filepath, const QString &friendlyName, bool usingAsm) {
+ QFile file(filepath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) {
- logError(QString("Could not write to file \"%1\"").arg(metatileFile));
+ logError(QString("Could not write to file \"%1\"").arg(filepath));
return false;
}
diff --git a/src/editor.cpp b/src/editor.cpp
index 174d0b07..058173da 100644
--- a/src/editor.cpp
+++ b/src/editor.cpp
@@ -238,7 +238,7 @@ void Editor::displayWildMonTables() {
labelComboStrings.sort();
labelCombo->addItems(labelComboStrings);
- labelCombo->setCurrentText(labelCombo->itemText(0));
+ labelCombo->setCurrentIndex(0);
QStackedWidget *stack = ui->stackedWidget_WildMons;
int labelIndex = 0;
@@ -495,7 +495,9 @@ void Editor::configureEncounterJSON(QWidget *window) {
QFrame *slotChoiceFrame = new QFrame;
QVBoxLayout *slotChoiceLayout = new QVBoxLayout;
if (useGroups) {
- QComboBox *groupCombo = new QComboBox;
+ auto groupCombo = new NoScrollComboBox;
+ groupCombo->setEditable(false);
+ groupCombo->setMinimumContentsLength(10);
connect(groupCombo, QOverload::of(&QComboBox::textActivated), [&tempFields, ¤tField, &updateTotal, index](QString newGroupName) {
for (EncounterField &field : tempFields) {
if (field.name == currentField.name) {
@@ -526,7 +528,7 @@ void Editor::configureEncounterJSON(QWidget *window) {
break;
}
}
- groupCombo->setCurrentText(currentGroupName);
+ groupCombo->setTextItem(currentGroupName);
slotChoiceLayout->addWidget(groupCombo);
}
slotChoiceLayout->addWidget(chanceSpinner);
@@ -982,7 +984,7 @@ QString Editor::getDivingMapName(const QString &direction) const {
void Editor::onDivingMapEditingFinished(NoScrollComboBox *combo, const QString &direction) {
if (!setDivingMapName(combo->currentText(), direction)) {
// If user input was invalid, restore the combo to the previously-valid text.
- combo->setCurrentText(getDivingMapName(direction));
+ combo->setTextItem(getDivingMapName(direction));
}
}
@@ -1163,7 +1165,7 @@ void Editor::onHoveredMapMetatileChanged(const QPoint &pos) {
void Editor::onHoveredMapMetatileCleared() {
this->setCursorRectVisible(false);
- if (!map_item->getEditsEnabled()) {
+ if (map_item->getEditsEnabled()) {
this->ui->statusBar->clearMessage();
}
Scripting::cb_BlockHoverCleared();
@@ -1281,8 +1283,8 @@ bool Editor::setLayout(QString layoutId) {
ui->comboBox_PrimaryTileset->blockSignals(true);
ui->comboBox_SecondaryTileset->blockSignals(true);
- ui->comboBox_PrimaryTileset->setCurrentText(this->layout->tileset_primary_label);
- ui->comboBox_SecondaryTileset->setCurrentText(this->layout->tileset_secondary_label);
+ ui->comboBox_PrimaryTileset->setTextItem(this->layout->tileset_primary_label);
+ ui->comboBox_SecondaryTileset->setTextItem(this->layout->tileset_secondary_label);
ui->comboBox_PrimaryTileset->blockSignals(false);
ui->comboBox_SecondaryTileset->blockSignals(false);
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 4e82dce4..322d6e83 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -657,13 +657,15 @@ bool MainWindow::openProject(QString dir, bool initial) {
this->statusBar()->showMessage(openMessage);
logInfo(openMessage);
+ porysplash->start();
+
+ porysplash->showLoadingMessage("config");
userConfig.projectDir = dir;
userConfig.load();
projectConfig.projectDir = dir;
projectConfig.load();
- porysplash->start();
-
+ porysplash->showLoadingMessage("custom scripts");
Scripting::init(this);
// Create the project
@@ -681,6 +683,7 @@ bool MainWindow::openProject(QString dir, bool initial) {
this->editor->setProject(project);
// Make sure project looks reasonable before attempting to load it
+ porysplash->showMessage("Verifying project");
if (isInvalidProject(this->editor->project)) {
delete this->editor->project;
porysplash->stop();
@@ -719,6 +722,7 @@ bool MainWindow::openProject(QString dir, bool initial) {
}
bool MainWindow::loadProjectData() {
+ porysplash->showLoadingMessage("project");
bool success = editor->project->load();
Scripting::populateGlobalObject(this);
return success;
@@ -786,6 +790,12 @@ bool MainWindow::checkProjectVersion(Project *project) {
}
void MainWindow::showProjectOpenFailure() {
+ if (!this->isVisible()){
+ // The main window is not visible during the initial project open; the splash screen is busy providing visual feedback.
+ // If project opening fails we can immediately display the empty main window (which we need anyway to parent messages to).
+ restoreWindowState();
+ show();
+ }
RecentErrorMessage::show(QStringLiteral("There was an error opening the project."), this);
}
@@ -807,6 +817,8 @@ bool MainWindow::isProjectOpen() {
}
bool MainWindow::setInitialMap() {
+ porysplash->showMessage("Opening initial map");
+
const QString recent = userConfig.recentMapOrLayout;
if (editor->project->mapNames.contains(recent)) {
// User recently had a map open that still exists.
@@ -1182,8 +1194,8 @@ void MainWindow::displayMapProperties() {
const QSignalBlocker b_PrimaryTileset(ui->comboBox_PrimaryTileset);
const QSignalBlocker b_SecondaryTileset(ui->comboBox_SecondaryTileset);
- ui->comboBox_PrimaryTileset->setCurrentText(editor->map->layout()->tileset_primary_label);
- ui->comboBox_SecondaryTileset->setCurrentText(editor->map->layout()->tileset_secondary_label);
+ ui->comboBox_PrimaryTileset->setTextItem(editor->map->layout()->tileset_primary_label);
+ ui->comboBox_SecondaryTileset->setTextItem(editor->map->layout()->tileset_secondary_label);
ui->mapCustomAttributesFrame->table()->setAttributes(editor->map->customAttributes());
}
@@ -1203,7 +1215,7 @@ void MainWindow::on_comboBox_LayoutSelector_currentTextChanged(const QString &te
// New layout failed to load, restore previous layout
const QSignalBlocker b(ui->comboBox_LayoutSelector);
- ui->comboBox_LayoutSelector->setCurrentText(this->editor->map->layout()->id);
+ ui->comboBox_LayoutSelector->setTextItem(this->editor->map->layout()->id);
return;
}
this->editor->map->setLayout(layout);
@@ -1219,12 +1231,14 @@ void MainWindow::onLayoutSelectorEditingFinished() {
const QString text = ui->comboBox_LayoutSelector->currentText();
if (!this->editor->project->mapLayouts.contains(text)) {
const QSignalBlocker b(ui->comboBox_LayoutSelector);
- ui->comboBox_LayoutSelector->setCurrentText(this->editor->layout->id);
+ ui->comboBox_LayoutSelector->setTextItem(this->editor->layout->id);
}
}
// Update the UI using information we've read from the user's project files.
bool MainWindow::setProjectUI() {
+ porysplash->showLoadingMessage("project UI");
+
Project *project = editor->project;
this->mapHeaderForm->setProject(project);
@@ -2722,7 +2736,7 @@ void MainWindow::openWildMonTable(const QString &mapName, const QString &groupNa
if (userSetMap(mapName)) {
// Switch to the correct main tab, wild encounter group, and wild encounter type tab.
on_mainTabBar_tabBarClicked(MainTab::WildPokemon);
- ui->comboBox_EncounterGroupLabel->setCurrentText(groupName);
+ ui->comboBox_EncounterGroupLabel->setTextItem(groupName);
QWidget *w = ui->stackedWidget_WildMons->currentWidget();
if (w) static_cast(w)->setCurrentField(fieldName);
}
diff --git a/src/project.cpp b/src/project.cpp
index b340ed27..f378cfcb 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -187,6 +187,7 @@ int Project::getSupportedMajorVersion(QString *errorOut) {
}
bool Project::load() {
+ this->parser.setUpdatesSplashScreen(true);
resetFileCache();
this->disabledSettingsNames.clear();
bool success = readGlobalConstants()
@@ -227,6 +228,7 @@ bool Project::load() {
initNewMapSettings();
applyParsedLimits();
}
+ this->parser.setUpdatesSplashScreen(false);
return success;
}
@@ -247,7 +249,9 @@ void Project::resetFileCache() {
projectConfig.getFilePath(ProjectFilePath::global_fieldmap),
};
for (const auto &path : filepaths) {
- this->parser.cacheFile(path);
+ if (this->parser.cacheFile(path)) {
+ watchFile(path);
+ }
}
}
@@ -327,6 +331,7 @@ QSet 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);
+ watchFile(mapFilepath);
QString error;
if (!parser.tryParseJsonFile(out, mapFilepath, &error)) {
logError(QString("Failed to read map data from '%1': %2").arg(mapFilepath).arg(error));
@@ -597,7 +602,7 @@ bool Project::readMapLayouts() {
clearMapLayouts();
const QString layoutsFilepath = projectConfig.getFilePath(ProjectFilePath::json_layouts);
- fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(layoutsFilepath));
+ watchFile(layoutsFilepath);
QJsonDocument layoutsDoc;
QString error;
if (!parser.tryParseJsonFile(&layoutsDoc, layoutsFilepath, &error)) {
@@ -751,11 +756,26 @@ bool Project::saveMapLayouts() {
return true;
}
-void Project::ignoreWatchedFileTemporarily(QString filepath) {
+void Project::watchFile(const QString &filename) {
+ this->fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(filename));
+}
+
+void Project::watchFiles(const QStringList &filenames) {
+ for (const auto &filename : filenames)
+ watchFile(filename);
+}
+
+void Project::ignoreWatchedFileTemporarily(const QString &filepath) {
// Ignore any file-change events for this filepath for the next 5 seconds.
this->modifiedFileTimestamps.insert(filepath, QDateTime::currentMSecsSinceEpoch() + 5000);
}
+void Project::ignoreWatchedFilesTemporarily(const QStringList &filepaths) {
+ for (const auto &filepath : filepaths) {
+ ignoreWatchedFileTemporarily(filepath);
+ }
+}
+
void Project::recordFileChange(const QString &filepath) {
if (this->modifiedFiles.contains(filepath)) {
// We already recorded a change to this file
@@ -1366,6 +1386,8 @@ bool Project::saveMap(Map *map, bool skipLayout) {
// Custom header fields.
OrderedJson::append(&mapObj, map->customAttributes());
+ ignoreWatchedFileTemporarily(mapFilepath);
+
OrderedJson mapJson(mapObj);
OrderedJsonDoc jsonDoc(&mapJson);
jsonDoc.dump(&mapFile);
@@ -1565,12 +1587,25 @@ Tileset *Project::createNewTileset(QString name, bool secondary, bool checkerboa
labelList->insert(i, tileset->name);
this->tilesetLabelsOrdered.append(tileset->name);
+ // Append to tileset specific files.
// TODO: Ideally we wouldn't save new Tilesets immediately
- // Append to tileset specific files. Strip prefix from name to get base name for use in other symbols.
- name.remove(0, prefix.length());
- tileset->appendToHeaders(this->root, name, this->usingAsmTilesets);
- tileset->appendToGraphics(this->root, name, this->usingAsmTilesets);
- tileset->appendToMetatiles(this->root, name, this->usingAsmTilesets);
+ QString headersFilepath = this->root + "/";
+ QString graphicsFilepath = this->root + "/";
+ QString metatilesFilepath = this->root + "/";
+ if (this->usingAsmTilesets) {
+ headersFilepath.append(projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm));
+ graphicsFilepath.append(projectConfig.getFilePath(ProjectFilePath::tilesets_graphics_asm));
+ metatilesFilepath.append(projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles_asm));
+ } else {
+ headersFilepath.append(projectConfig.getFilePath(ProjectFilePath::tilesets_headers));
+ graphicsFilepath.append(projectConfig.getFilePath(ProjectFilePath::tilesets_graphics));
+ metatilesFilepath.append(projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles));
+ }
+ ignoreWatchedFilesTemporarily({headersFilepath, graphicsFilepath, metatilesFilepath});
+ name.remove(0, prefix.length()); // Strip prefix from name to get base name for use in other symbols.
+ tileset->appendToHeaders(headersFilepath, name, this->usingAsmTilesets);
+ tileset->appendToGraphics(graphicsFilepath, name, this->usingAsmTilesets);
+ tileset->appendToMetatiles(metatilesFilepath, name, this->usingAsmTilesets);
tileset->save();
@@ -1594,7 +1629,7 @@ bool Project::readTilesetMetatileLabels() {
unusedMetatileLabels.clear();
QString metatileLabelsFilename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_labels);
- fileWatcher.addPath(root + "/" + metatileLabelsFilename);
+ watchFile(metatileLabelsFilename);
const QSet regexList = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix))};
const auto defines = parser.readCDefinesByRegex(metatileLabelsFilename, regexList);
@@ -1702,7 +1737,7 @@ bool Project::readWildMonData() {
const QString encounterRateFile = projectConfig.getFilePath(ProjectFilePath::wild_encounter);
const QString maxEncounterRateName = projectConfig.getIdentifier(ProjectIdentifier::define_max_encounter_rate);
- fileWatcher.addPath(QString("%1/%2").arg(root).arg(encounterRateFile));
+ watchFile(encounterRateFile);
auto defines = parser.readCDefinesByName(encounterRateFile, {maxEncounterRateName});
if (defines.contains(maxEncounterRateName))
this->maxEncounterRate = defines.value(maxEncounterRateName)/16;
@@ -1711,8 +1746,7 @@ bool Project::readWildMonData() {
const QString levelRangeFile = projectConfig.getFilePath(ProjectFilePath::constants_pokemon);
const QString minLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_min_level);
const QString maxLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_max_level);
-
- fileWatcher.addPath(QString("%1/%2").arg(root).arg(levelRangeFile));
+ watchFile(levelRangeFile);
defines = parser.readCDefinesByName(levelRangeFile, {minLevelName, maxLevelName});
if (defines.contains(minLevelName))
this->pokemonMinLevel = defines.value(minLevelName);
@@ -1724,7 +1758,7 @@ bool Project::readWildMonData() {
// Read encounter data
const QString wildMonJsonFilepath = projectConfig.getFilePath(ProjectFilePath::json_wild_encounters);
- fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(wildMonJsonFilepath));
+ watchFile(wildMonJsonFilepath);
OrderedJson::object wildMonObj;
QString error;
@@ -1881,7 +1915,7 @@ bool Project::readMapGroups() {
this->customMapGroupsData = QJsonObject();
const QString filepath = projectConfig.getFilePath(ProjectFilePath::json_map_groups);
- fileWatcher.addPath(root + "/" + filepath);
+ watchFile(filepath);
QJsonDocument mapGroupsDoc;
QString error;
if (!parser.tryParseJsonFile(&mapGroupsDoc, filepath, &error)) {
@@ -2184,7 +2218,7 @@ bool Project::readTilesetLabels() {
// If the tileset headers file is missing, the user may still have the old assembly format.
this->usingAsmTilesets = true;
QString asm_filename = projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm);
- QString text = parser.readTextFile(this->root + "/" + asm_filename);
+ QString text = parser.loadTextFile(asm_filename);
if (text.isEmpty()) {
logError(QString("Failed to read tileset labels from '%1' or '%2'.").arg(filename).arg(asm_filename));
return false;
@@ -2231,7 +2265,7 @@ bool Project::readFieldmapProperties() {
const QString mapOffsetHeightName = projectConfig.getIdentifier(ProjectIdentifier::define_map_offset_height);
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_fieldmap);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
const auto defines = parser.readCDefinesByName(filename, { numTilesPrimaryName,
numTilesTotalName,
numMetatilesPrimaryName,
@@ -2335,8 +2369,7 @@ bool Project::readFieldmapMasks() {
const QString behaviorMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_behavior);
const QString layerTypeMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_layer);
- const QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
- fileWatcher.addPath(root + "/" + globalFieldmap);
+ const QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap); // File already being watched
const auto defines = parser.readCDefinesByName(globalFieldmap, { metatileIdMaskName,
collisionMaskName,
elevationMaskName,
@@ -2391,7 +2424,7 @@ bool Project::readFieldmapMasks() {
const QString layerTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_layer);
const QString encounterTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_encounter);
const QString terrainTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_terrain);
- fileWatcher.addPath(root + "/" + srcFieldmap);
+ watchFile(srcFieldmap);
bool ok;
// Read terrain type mask
@@ -2469,7 +2502,7 @@ bool Project::readRegionMapSections() {
logError(QString("Failed to read region map sections from '%1': %2").arg(filepath).arg(error));
return false;
}
- fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(filepath));
+ watchFile(filepath);
QJsonObject mapSectionsGlobalObj = doc.object();
QJsonArray mapSections = mapSectionsGlobalObj.take("map_sections").toArray();
@@ -2633,7 +2666,7 @@ bool Project::readHealLocations() {
logError(QString("Failed to read heal locations from '%1': %2").arg(filepath).arg(error));
return false;
}
- fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(filepath));
+ watchFile(filepath);
QJsonObject healLocationsObj = doc.object();
QJsonArray healLocations = healLocationsObj.take("heal_locations").toArray();
@@ -2656,7 +2689,7 @@ bool Project::readHealLocations() {
bool Project::readItemNames() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_items);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->itemNames = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_items)}, &error);
if (!error.isEmpty())
@@ -2666,7 +2699,7 @@ bool Project::readItemNames() {
bool Project::readFlagNames() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_flags);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->flagNames = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_flags)}, &error);
if (!error.isEmpty())
@@ -2676,7 +2709,7 @@ bool Project::readFlagNames() {
bool Project::readVarNames() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_vars);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->varNames = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_vars)}, &error);
if (!error.isEmpty())
@@ -2686,7 +2719,7 @@ bool Project::readVarNames() {
bool Project::readMovementTypes() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_event_movement);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->movementTypes = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_movement_types)}, &error);
if (!error.isEmpty())
@@ -2696,7 +2729,7 @@ bool Project::readMovementTypes() {
bool Project::readInitialFacingDirections() {
QString filename = projectConfig.getFilePath(ProjectFilePath::initial_facing_table);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->facingDirections = parser.readNamedIndexCArray(filename, projectConfig.getIdentifier(ProjectIdentifier::symbol_facing_directions), &error);
if (!error.isEmpty())
@@ -2706,7 +2739,7 @@ bool Project::readInitialFacingDirections() {
bool Project::readMapTypes() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
- fileWatcher.addPath(root + "/" + filename);
+ // File already being watched
QString error;
this->mapTypes = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_map_types)}, &error);
if (!error.isEmpty())
@@ -2716,7 +2749,7 @@ bool Project::readMapTypes() {
bool Project::readMapBattleScenes() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
- fileWatcher.addPath(root + "/" + filename);
+ // File already being watched
QString error;
this->mapBattleScenes = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_battle_scenes)}, &error);
if (!error.isEmpty())
@@ -2726,7 +2759,7 @@ bool Project::readMapBattleScenes() {
bool Project::readWeatherNames() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->weatherNames = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_weather)}, &error);
if (!error.isEmpty())
@@ -2739,7 +2772,7 @@ bool Project::readCoordEventWeatherNames() {
return true;
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->coordEventWeatherNames = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_coord_event_weather)}, &error);
if (!error.isEmpty())
@@ -2752,7 +2785,7 @@ bool Project::readSecretBaseIds() {
return true;
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_secret_bases);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->secretBaseIds = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_secret_bases)}, &error);
if (!error.isEmpty())
@@ -2762,7 +2795,7 @@ bool Project::readSecretBaseIds() {
bool Project::readBgEventFacingDirections() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_event_bg);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->bgEventFacingDirections = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_sign_facing_directions)}, &error);
if (!error.isEmpty())
@@ -2772,7 +2805,7 @@ bool Project::readBgEventFacingDirections() {
bool Project::readTrainerTypes() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_trainer_types);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->trainerTypes = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_trainer_types)}, &error);
if (!error.isEmpty())
@@ -2785,7 +2818,7 @@ bool Project::readMetatileBehaviors() {
this->metatileBehaviorMapInverse.clear();
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_behaviors);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
const auto defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)}, &error);
if (defines.isEmpty() && projectConfig.metatileBehaviorMask) {
@@ -2807,7 +2840,7 @@ bool Project::readMetatileBehaviors() {
bool Project::readSongNames() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_songs);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
this->songNames = parser.readCDefineNames(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_music)}, &error);
if (!error.isEmpty())
@@ -2822,7 +2855,7 @@ bool Project::readSongNames() {
bool Project::readObjEventGfxConstants() {
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_events);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
QString error;
const auto defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)}, &error);
if (!error.isEmpty())
@@ -2838,7 +2871,7 @@ bool Project::readObjEventGfxConstants() {
bool Project::readMiscellaneousConstants() {
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_global);
const QString maxObjectEventsName = projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count);
- fileWatcher.addPath(root + "/" + filename);
+ watchFile(filename);
const auto defines = parser.readCDefinesByName(filename, {maxObjectEventsName});
this->maxObjectEvents = 64; // Default value
@@ -2965,7 +2998,7 @@ bool Project::readEventGraphics() {
const QString gfxInfoFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
const QString picTablesFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_pic_tables);
const QString gfxFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx);
- fileWatcher.addPaths({pointersFilepath, gfxInfoFilepath, picTablesFilepath, gfxFilepath});
+ watchFiles({pointersFilepath, gfxInfoFilepath, picTablesFilepath, gfxFilepath});
// Read the table mapping OBJ_EVENT_GFX constants to the names of pointers to data about their graphics.
const QString pointersName = projectConfig.getIdentifier(ProjectIdentifier::symbol_obj_event_gfx_pointers);
@@ -3166,14 +3199,14 @@ bool Project::readSpeciesIconPaths() {
// Read map of species constants to icon names
const QString srcfilename = projectConfig.getFilePath(ProjectFilePath::pokemon_icon_table);
- fileWatcher.addPath(this->root + "/" + srcfilename);
+ watchFile(srcfilename);
const QString tableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_pokemon_icon_table);
const QMap monIconNames = parser.readNamedIndexCArray(srcfilename, tableName);
// Read species constants. If this fails we can get them from the icon table (but we shouldn't rely on it).
const QString speciesPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_species_prefix);
const QString constantsFilename = projectConfig.getFilePath(ProjectFilePath::constants_species);
- fileWatcher.addPath(this->root + "/" + constantsFilename);
+ watchFile(constantsFilename);
this->speciesNames = parser.readCDefineNames(constantsFilename, {QString("\\b%1").arg(speciesPrefix)});
if (this->speciesNames.isEmpty()) {
this->speciesNames = monIconNames.keys();
@@ -3186,7 +3219,7 @@ bool Project::readSpeciesIconPaths() {
// do this on request in Project::getDefaultSpeciesIconPath.
if (!monIconNames.isEmpty()) {
const QString iconGraphicsFile = projectConfig.getFilePath(ProjectFilePath::data_pokemon_gfx);
- fileWatcher.addPath(this->root + "/" + iconGraphicsFile);
+ watchFile(iconGraphicsFile);
QMap iconNameToFilepath = parser.readCIncbinMulti(iconGraphicsFile);
for (auto i = monIconNames.constBegin(); i != monIconNames.constEnd(); i++) {
diff --git a/src/ui/aboutporymap.cpp b/src/ui/aboutporymap.cpp
index 5aa5f0c8..2f7246c0 100644
--- a/src/ui/aboutporymap.cpp
+++ b/src/ui/aboutporymap.cpp
@@ -8,20 +8,20 @@ AboutPorymap::AboutPorymap(QWidget *parent) :
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
- static const QString commitHash = PORYMAP_LATEST_COMMIT;
this->ui->label_Version->setText(getVersionString());
layout()->setSizeConstraint(QLayout::SetFixedSize);
}
QString AboutPorymap::getVersionString() {
- static const QString commitHash = PORYMAP_LATEST_COMMIT;
- return QString("Version %1%2\nQt %3 (%4)\n%5")
+ static const QString commitHash = QStringLiteral(PORYMAP_LATEST_COMMIT);
+ static const QString versionString = QString("Version %1%2\nQt %3 (%4)\n%5")
.arg(QCoreApplication::applicationVersion())
.arg(commitHash.isEmpty() ? "" : QString(" (%1)").arg(commitHash))
.arg(QStringLiteral(QT_VERSION_STR))
.arg(QSysInfo::buildCpuArchitecture())
.arg(QStringLiteral(__DATE__));
+ return versionString;
}
AboutPorymap::~AboutPorymap()
diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp
index 86df9525..b773f752 100644
--- a/src/ui/connectionslistitem.cpp
+++ b/src/ui/connectionslistitem.cpp
@@ -106,7 +106,7 @@ void ConnectionsListItem::commitDirection() {
if (MapConnection::isDiving(direction)) {
// Diving maps are displayed separately, no support right now for replacing a list item with a diving map.
// For now just restore the original direction.
- ui->comboBox_Direction->setCurrentText(this->connection->direction());
+ ui->comboBox_Direction->setTextItem(this->connection->direction());
return;
}
diff --git a/src/ui/divingmappixmapitem.cpp b/src/ui/divingmappixmapitem.cpp
index b774b1e9..550e0037 100644
--- a/src/ui/divingmappixmapitem.cpp
+++ b/src/ui/divingmappixmapitem.cpp
@@ -1,7 +1,7 @@
#include "divingmappixmapitem.h"
#include "config.h"
-DivingMapPixmapItem::DivingMapPixmapItem(MapConnection *connection, QComboBox *combo)
+DivingMapPixmapItem::DivingMapPixmapItem(MapConnection *connection, NoScrollComboBox *combo)
: QGraphicsPixmapItem(getBasePixmap(connection))
{
m_connection = connection;
@@ -38,5 +38,5 @@ void DivingMapPixmapItem::onTargetMapChanged() {
}
void DivingMapPixmapItem::setComboText(const QString &text) {
- if (m_combo) m_combo->setCurrentText(text);
+ if (m_combo) m_combo->setTextItem(text);
}
diff --git a/src/ui/encountertabledelegates.cpp b/src/ui/encountertabledelegates.cpp
index 2d46f54f..12e105bb 100644
--- a/src/ui/encountertabledelegates.cpp
+++ b/src/ui/encountertabledelegates.cpp
@@ -28,7 +28,7 @@ QWidget *SpeciesComboDelegate::createEditor(QWidget *parent, const QStyleOptionV
void SpeciesComboDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
QString species = index.data(Qt::EditRole).toString();
NoScrollComboBox *combo = static_cast(editor);
- combo->setCurrentText(species);
+ combo->setTextItem(species);
}
void SpeciesComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
diff --git a/src/ui/eventframes.cpp b/src/ui/eventframes.cpp
index 95a31557..35d58831 100644
--- a/src/ui/eventframes.cpp
+++ b/src/ui/eventframes.cpp
@@ -152,8 +152,12 @@ void EventFrame::initialize() {
this->label_icon->setPixmap(this->event->getPixmap());
}
-void EventFrame::populate(Project *) {
+void EventFrame::populate(Project *project) {
this->populated = true;
+ if (this->project && this->project != project) {
+ this->project->disconnect(this);
+ }
+ this->project = project;
}
void EventFrame::invalidateConnections() {
@@ -166,6 +170,10 @@ void EventFrame::invalidateUi() {
void EventFrame::invalidateValues() {
this->populated = false;
+ if (this->isVisible()) {
+ // Repopulate immediately
+ this->populate(this->project);
+ }
}
void EventFrame::setActive(bool active) {
@@ -181,19 +189,20 @@ void EventFrame::populateDropdown(NoScrollComboBox * combo, const QStringList &i
const QString savedText = combo->currentText();
combo->clear();
combo->addItems(items);
- combo->setCurrentText(savedText);
+ combo->setTextItem(savedText);
}
void EventFrame::populateScriptDropdown(NoScrollComboBox * combo, Project * project) {
// The script dropdown and autocomplete are populated with scripts used by the map's events and from its scripts file.
- if (!this->event->getMap())
+ Map *map = this->event ? this->event->getMap() : nullptr;
+ if (!map)
return;
- QStringList scripts = this->event->getMap()->getScriptLabels(this->event->getEventGroup());
+ QStringList scripts = map->getScriptLabels(this->event->getEventGroup());
populateDropdown(combo, scripts);
// Depending on the settings, the autocomplete may also contain all global scripts.
- if (porymapConfig.loadAllEventScripts) {
+ if (project && porymapConfig.loadAllEventScripts) {
project->insertGlobalScriptLabels(scripts);
}
@@ -209,14 +218,23 @@ void EventFrame::populateScriptDropdown(NoScrollComboBox * combo, Project * proj
combo->setCompleter(completer);
- // If the project changes the script labels, update the EventFrame.
- // TODO: At the moment this only happens when the user changes script settings (i.e. when 'porymapConfig.loadAllEventScripts' changes).
- // This should ultimately be connected to a file watcher so that we can also update the dropdown when the scripts file changes.
- connect(project, &Project::eventScriptLabelsRead, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
+ // If the script labels change then we need to update the EventFrame.
+ if (project) connect(project, &Project::eventScriptLabelsRead, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
+ connect(map, &Map::scriptsModified, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
+}
+
+void EventFrame::populateMapNameDropdown(NoScrollComboBox * combo, Project * project) {
+ if (!project)
+ return;
+
+ populateDropdown(combo, project->mapNames);
+
+ // This frame type displays map names, so when a new map is created we need to repopulate it.
+ connect(project, &Project::mapCreated, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
}
void EventFrame::populateIdNameDropdown(NoScrollComboBox * combo, Project * project, const QString &mapName, Event::Group group) {
- if (!project->mapNames.contains(mapName))
+ if (!project || !project->mapNames.contains(mapName))
return;
Map *map = project->loadMap(mapName);
@@ -325,7 +343,6 @@ void ObjectFrame::connectSignals(MainWindow *window) {
if (this->connected) return;
EventFrame::connectSignals(window);
- Project *project = window->editor->project;
// local id
this->line_edit_local_id->disconnect();
@@ -336,18 +353,18 @@ void ObjectFrame::connectSignals(MainWindow *window) {
// sprite update
this->combo_sprite->disconnect();
- connect(this->combo_sprite, &QComboBox::currentTextChanged, [this, project](const QString &text) {
+ connect(this->combo_sprite, &QComboBox::currentTextChanged, [this](const QString &text) {
this->object->setGfx(text);
- this->object->getPixmapItem()->render(project);
+ this->object->getPixmapItem()->render(this->project);
this->object->modify();
});
connect(this->object->getPixmapItem(), &EventPixmapItem::rendered, this->label_icon, &QLabel::setPixmap);
// movement
this->combo_movement->disconnect();
- connect(this->combo_movement, &QComboBox::currentTextChanged, [this, project](const QString &text) {
+ connect(this->combo_movement, &QComboBox::currentTextChanged, [this](const QString &text) {
this->object->setMovement(text);
- this->object->getPixmapItem()->render(project);
+ this->object->getPixmapItem()->render(this->project);
this->object->modify();
});
@@ -419,7 +436,7 @@ void ObjectFrame::initialize() {
this->spinner_radius_y->setValue(this->object->getRadiusY());
// script
- this->combo_script->setCurrentText(this->object->getScript());
+ this->combo_script->setTextItem(this->object->getScript());
if (porymapConfig.textEditorGotoLine.isEmpty())
this->button_script->hide();
@@ -430,7 +447,7 @@ void ObjectFrame::initialize() {
this->combo_trainer_type->setTextItem(this->object->getTrainerType());
// sight berry
- this->combo_radius_treeid->setCurrentText(this->object->getSightRadiusBerryTreeID());
+ this->combo_radius_treeid->setTextItem(this->object->getSightRadiusBerryTreeID());
}
void ObjectFrame::populate(Project *project) {
@@ -498,7 +515,6 @@ void CloneObjectFrame::connectSignals(MainWindow *window) {
if (this->connected) return;
EventFrame::connectSignals(window);
- Project *project = window->editor->project;
// local id
this->line_edit_local_id->disconnect();
@@ -512,26 +528,23 @@ void CloneObjectFrame::connectSignals(MainWindow *window) {
// target map
this->combo_target_map->disconnect();
- connect(this->combo_target_map, &QComboBox::currentTextChanged, [this, project](const QString &mapName) {
+ connect(this->combo_target_map, &QComboBox::currentTextChanged, [this](const QString &mapName) {
this->clone->setTargetMap(mapName);
- this->clone->getPixmapItem()->render(project);
- this->combo_sprite->setCurrentText(this->clone->getGfx());
+ this->clone->getPixmapItem()->render(this->project);
+ this->combo_sprite->setTextItem(this->clone->getGfx());
this->clone->modify();
- populateIdNameDropdown(this->combo_target_id, project, mapName, Event::Group::Object);
+ populateIdNameDropdown(this->combo_target_id, this->project, mapName, Event::Group::Object);
});
connect(window, &MainWindow::mapOpened, this, &CloneObjectFrame::tryInvalidateIdDropdown, Qt::UniqueConnection);
// target id
this->combo_target_id->disconnect();
- connect(this->combo_target_id, &QComboBox::currentTextChanged, [this, project](const QString &text) {
+ connect(this->combo_target_id, &QComboBox::currentTextChanged, [this](const QString &text) {
this->clone->setTargetID(text);
- this->clone->getPixmapItem()->render(project);
- this->combo_sprite->setCurrentText(this->clone->getGfx());
+ this->clone->getPixmapItem()->render(this->project);
+ this->combo_sprite->setTextItem(this->clone->getGfx());
this->clone->modify();
});
-
- // This frame type displays map names, so when a new map is created we need to repopulate it.
- connect(project, &Project::mapCreated, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
}
void CloneObjectFrame::tryInvalidateIdDropdown(Map *map) {
@@ -552,10 +565,10 @@ void CloneObjectFrame::initialize() {
this->line_edit_local_id->setText(this->clone->getIdName());
// sprite
- this->combo_sprite->setCurrentText(this->clone->getGfx());
+ this->combo_sprite->setTextItem(this->clone->getGfx());
// target id
- this->combo_target_id->setCurrentText(this->clone->getTargetID());
+ this->combo_target_id->setTextItem(this->clone->getTargetID());
// target map
this->combo_target_map->setTextItem(this->clone->getTargetMap());
@@ -567,7 +580,7 @@ void CloneObjectFrame::populate(Project *project) {
const QSignalBlocker blocker(this);
EventFrame::populate(project);
- populateDropdown(this->combo_target_map, project->mapNames);
+ populateMapNameDropdown(this->combo_target_map, project);
populateIdNameDropdown(this->combo_target_id, project, this->clone->getTargetMap(), Event::Group::Object);
}
@@ -618,7 +631,6 @@ void WarpFrame::connectSignals(MainWindow *window) {
if (this->connected) return;
EventFrame::connectSignals(window);
- Project *project = window->editor->project;
// id
this->line_edit_id->disconnect();
@@ -629,10 +641,10 @@ void WarpFrame::connectSignals(MainWindow *window) {
// dest map
this->combo_dest_map->disconnect();
- connect(this->combo_dest_map, &QComboBox::currentTextChanged, [this, project](const QString &mapName) {
+ connect(this->combo_dest_map, &QComboBox::currentTextChanged, [this](const QString &mapName) {
this->warp->setDestinationMap(mapName);
this->warp->modify();
- populateIdNameDropdown(this->combo_dest_warp, project, mapName, Event::Group::Warp);
+ populateIdNameDropdown(this->combo_dest_warp, this->project, mapName, Event::Group::Warp);
});
connect(window, &MainWindow::mapOpened, this, &WarpFrame::tryInvalidateIdDropdown, Qt::UniqueConnection);
@@ -646,9 +658,6 @@ void WarpFrame::connectSignals(MainWindow *window) {
// warning
this->warning->disconnect();
connect(this->warning, &QPushButton::clicked, window, &MainWindow::onWarpBehaviorWarningClicked);
-
- // This frame type displays map names, so when a new map is created we need to repopulate it.
- connect(project, &Project::mapCreated, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
}
void WarpFrame::tryInvalidateIdDropdown(Map *map) {
@@ -672,7 +681,7 @@ void WarpFrame::initialize() {
this->combo_dest_map->setTextItem(this->warp->getDestinationMap());
// dest id
- this->combo_dest_warp->setCurrentText(this->warp->getDestinationWarpID());
+ this->combo_dest_warp->setTextItem(this->warp->getDestinationWarpID());
}
void WarpFrame::populate(Project *project) {
@@ -681,7 +690,7 @@ void WarpFrame::populate(Project *project) {
const QSignalBlocker blocker(this);
EventFrame::populate(project);
- populateDropdown(this->combo_dest_map, project->mapNames);
+ populateMapNameDropdown(this->combo_dest_map, project);
populateIdNameDropdown(this->combo_dest_warp, project, this->warp->getDestinationMap(), Event::Group::Warp);
}
@@ -753,13 +762,13 @@ void TriggerFrame::initialize() {
EventFrame::initialize();
// script
- this->combo_script->setCurrentText(this->trigger->getScriptLabel());
+ this->combo_script->setTextItem(this->trigger->getScriptLabel());
// var
this->combo_var->setTextItem(this->trigger->getScriptVar());
// var value
- this->combo_var_value->setCurrentText(this->trigger->getScriptVarValue());
+ this->combo_var_value->setTextItem(this->trigger->getScriptVarValue());
}
void TriggerFrame::populate(Project *project) {
@@ -876,7 +885,7 @@ void SignFrame::initialize() {
this->combo_facing_dir->setTextItem(this->sign->getFacingDirection());
// script
- this->combo_script->setCurrentText(this->sign->getScriptLabel());
+ this->combo_script->setTextItem(this->sign->getScriptLabel());
}
void SignFrame::populate(Project *project) {
@@ -1102,7 +1111,6 @@ void HealLocationFrame::connectSignals(MainWindow *window) {
if (this->connected) return;
EventFrame::connectSignals(window);
- Project *project = window->editor->project;
this->line_edit_id->disconnect();
connect(this->line_edit_id, &QLineEdit::textChanged, [this](const QString &text) {
@@ -1111,10 +1119,10 @@ void HealLocationFrame::connectSignals(MainWindow *window) {
});
this->combo_respawn_map->disconnect();
- connect(this->combo_respawn_map, &QComboBox::currentTextChanged, [this, project](const QString &mapName) {
+ connect(this->combo_respawn_map, &QComboBox::currentTextChanged, [this](const QString &mapName) {
this->healLocation->setRespawnMapName(mapName);
this->healLocation->modify();
- populateIdNameDropdown(this->combo_respawn_npc, project, mapName, Event::Group::Object);
+ populateIdNameDropdown(this->combo_respawn_npc, this->project, mapName, Event::Group::Object);
});
connect(window, &MainWindow::mapOpened, this, &HealLocationFrame::tryInvalidateIdDropdown, Qt::UniqueConnection);
@@ -1123,9 +1131,6 @@ void HealLocationFrame::connectSignals(MainWindow *window) {
this->healLocation->setRespawnNPC(text);
this->healLocation->modify();
});
-
- // This frame type displays map names, so when a new map is created we need to repopulate it.
- connect(project, &Project::mapCreated, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
}
void HealLocationFrame::tryInvalidateIdDropdown(Map *map) {
@@ -1158,7 +1163,7 @@ void HealLocationFrame::populate(Project *project) {
EventFrame::populate(project);
if (projectConfig.healLocationRespawnDataEnabled) {
- populateDropdown(this->combo_respawn_map, project->mapNames);
+ populateMapNameDropdown(this->combo_respawn_map, project);
populateIdNameDropdown(this->combo_respawn_npc, project, this->healLocation->getRespawnMapName(), Event::Group::Object);
}
}
diff --git a/src/ui/gridsettings.cpp b/src/ui/gridsettings.cpp
index 87e0896a..4e36b60d 100644
--- a/src/ui/gridsettings.cpp
+++ b/src/ui/gridsettings.cpp
@@ -144,7 +144,7 @@ void GridSettingsDialog::updateInput() {
ui->colorInput->setColor(m_settings->color.rgb());
const QSignalBlocker b_Style(ui->comboBox_Style);
- ui->comboBox_Style->setCurrentText(GridSettings::getStyleName(m_settings->style));
+ ui->comboBox_Style->setTextItem(GridSettings::getStyleName(m_settings->style));
}
void GridSettingsDialog::setWidth(int value) {
diff --git a/src/ui/loadingscreen.cpp b/src/ui/loadingscreen.cpp
index 9b60cf92..18642afb 100644
--- a/src/ui/loadingscreen.cpp
+++ b/src/ui/loadingscreen.cpp
@@ -43,18 +43,37 @@ void PorymapLoadingScreen::stop () {
this->hide();
}
-void PorymapLoadingScreen::setPixmap(QPixmap pixmap) {
+void PorymapLoadingScreen::setPixmap(const QPixmap &pixmap) {
if (!this->isVisible()) return;
this->ui->labelPixmap->setPixmap(pixmap);
}
-void PorymapLoadingScreen::showMessage(QString text) {
+// Displays the message 'prefixtext...'. The 'text' portion may be elided if it's too long.
+void PorymapLoadingScreen::showMessage(const QString &prefix, const QString &text) {
if (!this->isVisible()) return;
- this->ui->labelText->setText(text.mid(text.lastIndexOf("/") + 1));
+
+ // Limit text (excluding prefix) to avoid increasing the splash screen's width.
+ static const QFontMetrics fontMetrics = this->ui->labelText->fontMetrics();
+ static const int maxWidth = this->ui->labelText->width() + 1;
+ int prefixWidth = fontMetrics.horizontalAdvance(prefix);
+ QString message = fontMetrics.elidedText(text + QStringLiteral("..."), Qt::ElideLeft, qMax(maxWidth - prefixWidth, 0));
+ message.prepend(prefix);
+
+ this->ui->labelText->setText(message);
QApplication::processEvents();
}
+// Displays the message 'text...'
+void PorymapLoadingScreen::showMessage(const QString &text) {
+ showMessage("", text);
+}
+
+// Displays the message 'Loading text...'
+void PorymapLoadingScreen::showLoadingMessage(const QString &text) {
+ showMessage(QStringLiteral("Loading "), text);
+}
+
void PorymapLoadingScreen::updateFrame() {
this->frame = (this->frame + 1) % this->splashImage.frameCount();
this->setPixmap(QPixmap::fromImage(this->splashImage.frame(this->frame)));
diff --git a/src/ui/mapheaderform.cpp b/src/ui/mapheaderform.cpp
index a2a0b8b5..991fe1c5 100644
--- a/src/ui/mapheaderform.cpp
+++ b/src/ui/mapheaderform.cpp
@@ -1,6 +1,5 @@
#include "mapheaderform.h"
#include "ui_mapheaderform.h"
-#include "project.h"
MapHeaderForm::MapHeaderForm(QWidget *parent)
: QWidget(parent)
@@ -94,7 +93,7 @@ void MapHeaderForm::setLocations(const QStringList &locations) {
const QString before = ui->comboBox_Location->currentText();
ui->comboBox_Location->clear();
ui->comboBox_Location->addItems(locations);
- ui->comboBox_Location->setCurrentText(before);
+ ui->comboBox_Location->setTextItem(before);
}
// Assign a MapHeader that the form will keep in sync with the UI.
@@ -187,10 +186,10 @@ void MapHeaderForm::setAllowsBiking(bool allowsBiking) { ui->checkBox_
void MapHeaderForm::setAllowsEscaping(bool allowsEscaping) { ui->checkBox_AllowEscaping->setChecked(allowsEscaping); }
void MapHeaderForm::setFloorNumber(int floorNumber) { ui->spinBox_FloorNumber->setValue(floorNumber); }
-// If we always call setText / setCurrentText the user's cursor may move to the end of the text while they're typing.
-void MapHeaderForm::setText(QComboBox *combo, const QString &text) const {
+// If we always call setText / setTextItem the user's cursor may move to the end of the text while they're typing.
+void MapHeaderForm::setText(NoScrollComboBox *combo, const QString &text) const {
if (combo->currentText() != text)
- combo->setCurrentText(text);
+ combo->setTextItem(text);
}
void MapHeaderForm::setText(QLineEdit *lineEdit, const QString &text) const {
if (lineEdit->text() != text)
diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp
index 732d3e83..05664aef 100644
--- a/src/ui/mapimageexporter.cpp
+++ b/src/ui/mapimageexporter.cpp
@@ -101,11 +101,11 @@ void MapImageExporter::setModeSpecificUi() {
ui->comboBox_MapSelection->clear();
if (m_map) {
ui->comboBox_MapSelection->addItems(m_project->mapNames);
- ui->comboBox_MapSelection->setCurrentText(m_map->name());
+ ui->comboBox_MapSelection->setTextItem(m_map->name());
ui->label_MapSelection->setText(m_mode == ImageExporterMode::Stitch ? QStringLiteral("Starting Map") : QStringLiteral("Map"));
} else if (m_layout) {
ui->comboBox_MapSelection->addItems(m_project->layoutIds);
- ui->comboBox_MapSelection->setCurrentText(m_layout->id);
+ ui->comboBox_MapSelection->setTextItem(m_layout->id);
ui->label_MapSelection->setText(QStringLiteral("Layout"));
}
@@ -146,7 +146,7 @@ void MapImageExporter::setLayout(Layout *layout) {
void MapImageExporter::setSelectionText(const QString &text) {
const QSignalBlocker b(ui->comboBox_MapSelection);
- ui->comboBox_MapSelection->setCurrentText(text);
+ ui->comboBox_MapSelection->setTextItem(text);
updateMapSelection();
}
@@ -171,7 +171,7 @@ void MapImageExporter::updateMapSelection() {
// Ensure text in the combo box remains valid
const QSignalBlocker b(ui->comboBox_MapSelection);
- ui->comboBox_MapSelection->setCurrentText(m_map ? m_map->name() : m_layout->id);
+ ui->comboBox_MapSelection->setTextItem(m_map ? m_map->name() : m_layout->id);
if (m_map != oldMap && (!m_map || !oldMap)) {
// Switching to or from layout-only mode
diff --git a/src/ui/newmapdialog.cpp b/src/ui/newmapdialog.cpp
index caa1e839..36819404 100644
--- a/src/ui/newmapdialog.cpp
+++ b/src/ui/newmapdialog.cpp
@@ -167,7 +167,7 @@ void NewMapDialog::on_lineEdit_Name_textChanged(const QString &text) {
// Changing the map name updates the layout ID field to match.
if (ui->comboBox_LayoutID->isEnabled()) {
- ui->comboBox_LayoutID->setCurrentText(Layout::layoutConstantFromName(text));
+ ui->comboBox_LayoutID->setTextItem(Layout::layoutConstantFromName(text));
}
}
diff --git a/src/ui/preferenceeditor.cpp b/src/ui/preferenceeditor.cpp
index f9071ec2..1289fe79 100644
--- a/src/ui/preferenceeditor.cpp
+++ b/src/ui/preferenceeditor.cpp
@@ -44,7 +44,7 @@ void PreferenceEditor::initFields() {
}
void PreferenceEditor::updateFields() {
- themeSelector->setCurrentText(porymapConfig.theme);
+ themeSelector->setTextItem(porymapConfig.theme);
if (porymapConfig.eventSelectionShapeMode == QGraphicsPixmapItem::MaskShape) {
ui->radioButton_OnSprite->setChecked(true);
} else if (porymapConfig.eventSelectionShapeMode == QGraphicsPixmapItem::BoundingRectShape) {
diff --git a/src/ui/regionmapeditor.cpp b/src/ui/regionmapeditor.cpp
index 493ea78e..0415e0f0 100644
--- a/src/ui/regionmapeditor.cpp
+++ b/src/ui/regionmapeditor.cpp
@@ -657,7 +657,7 @@ void RegionMapEditor::displayRegionMapLayoutOptions() {
void RegionMapEditor::updateRegionMapLayoutOptions(int index) {
const QSignalBlocker b_ConnectedMap(ui->comboBox_RM_ConnectedMap);
- this->ui->comboBox_RM_ConnectedMap->setCurrentText(this->region_map->squareMapSection(index));
+ this->ui->comboBox_RM_ConnectedMap->setTextItem(this->region_map->squareMapSection(index));
this->ui->pushButton_RM_Options_delete->setEnabled(this->region_map->squareHasMap(index));
@@ -736,7 +736,7 @@ void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
this->ui->pushButton_entryActivate->setEnabled(section != this->region_map->default_map_section);
this->ui->pushButton_entryActivate->setText(enabled ? "Remove" : "Add");
- this->ui->comboBox_RM_Entry_MapSection->setCurrentText(section);
+ this->ui->comboBox_RM_Entry_MapSection->setTextItem(section);
this->activeEntry = section;
this->region_map_entries_item->currentSection = section;
MapSectionEntry entry = enabled ? this->region_map_entries[section] : MapSectionEntry();
@@ -1296,11 +1296,11 @@ void RegionMapEditor::setLocations(const QStringList &locations) {
auto before = ui->comboBox_RM_ConnectedMap->currentText();
ui->comboBox_RM_ConnectedMap->clear();
ui->comboBox_RM_ConnectedMap->addItems(locations);
- ui->comboBox_RM_ConnectedMap->setCurrentText(before);
+ ui->comboBox_RM_ConnectedMap->setTextItem(before);
const QSignalBlocker b_MapSection(ui->comboBox_RM_Entry_MapSection);
before = ui->comboBox_RM_Entry_MapSection->currentText();
ui->comboBox_RM_Entry_MapSection->clear();
ui->comboBox_RM_Entry_MapSection->addItems(locations);
- ui->comboBox_RM_Entry_MapSection->setCurrentText(before);
+ ui->comboBox_RM_Entry_MapSection->setTextItem(before);
}
diff --git a/src/ui/wildmonchart.cpp b/src/ui/wildmonchart.cpp
index 521706d6..c6e18284 100644
--- a/src/ui/wildmonchart.cpp
+++ b/src/ui/wildmonchart.cpp
@@ -312,7 +312,7 @@ QBarSet* WildMonChart::createLevelDistributionBarSet(const QString &species, con
const QSignalBlocker blocker1(ui->groupBox_Species);
const QSignalBlocker blocker2(ui->comboBox_Species);
ui->groupBox_Species->setChecked(true);
- ui->comboBox_Species->setCurrentText(species);
+ ui->comboBox_Species->setTextItem(species);
refreshLevelDistributionChart();
});
}