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 -
noscrollcombobox.h
-
- - NoScrollSpinBox - QSpinBox -
noscrollspinbox.h
-
-
- - 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
QtCharts
+ + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
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(); }); }