Add unlockable icon

This commit is contained in:
GriffinR
2025-12-07 20:18:08 -05:00
parent dcef773a33
commit df98d62339
7 changed files with 266 additions and 1 deletions

View File

@@ -34,6 +34,7 @@
#include "newlayoutdialog.h"
#include "message.h"
#include "resizelayoutpopup.h"
#include "unlockableicon.h"
#if __has_include(<QJSValue>)
#include <QJSValue>
@@ -354,6 +355,8 @@ private:
MapNavigation forwardNavigation;
bool ignoreNavigationRecords = false;
UnlockableIcon unlockableMainTabIcon;
QAction *copyAction = nullptr;
QAction *pasteAction = nullptr;
@@ -460,7 +463,8 @@ private:
MapListToolBar* getCurrentMapListToolBar();
MapTree* getCurrentMapList();
void setLocationComboBoxes(const QStringList &locations);
void overrideMainTabIcons(const QIcon& icon);
void tryUnlockMainTabIcon(const Map* map);
QObjectList shortcutableObjects() const;
void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false);

View File

@@ -0,0 +1,57 @@
#ifndef UNLOCKABLEICON_H
#define UNLOCKABLEICON_H
// Manages an icon loaded from an obfuscated data file containing the icon's image data and a key.
// The icon can only be accessed by inputting the correct key.
#include <QObject>
#include <QIcon>
#include <QString>
#include <QSet>
class UnlockableIcon : public QObject
{
Q_OBJECT
public:
UnlockableIcon(QObject* parent = nullptr);
UnlockableIcon(const QString& dataFilepath, QObject* parent = nullptr);
~UnlockableIcon() {};
// Create the obfuscated data file to load an unlockable icon from.
// Normally unused, this is only needed to update the resource data file.
static bool createDataFile(const QString& inputFilepath, const QString& outputFilepath, const QString& key);
bool load(const QString& dataFilepath);
void clear();
// Try to unlock the icon by matching the next character in the key.
// Progress resets if the character is not a match.
void tryUnlock(const QChar& c);
// Try to unlock the icon by matching the next character in the key.
// Progress resets if none of the characters in the set are a match.
void tryUnlock(const QSet<QChar>& cSet);
// Try to unlock the icon by matching the remaining characters in the key.
// Progress resets if any character in the string is not a match.
void tryUnlock(const QString& key);
bool isUnlocked() const;
QIcon icon() const;
signals:
void unlocked(const QIcon& icon);
private:
QIcon m_icon;
QString m_key;
quint32 m_keyIndex = 0;
bool m_loaded = false;
bool canUnlock() const;
bool tryKeyMatch(const QSet<QChar>& cSet);
};
#endif // UNLOCKABLEICON_H

View File

@@ -148,6 +148,7 @@ SOURCES += src/core/advancemapparser.cpp \
src/ui/regionmappropertiesdialog.cpp \
src/ui/colorpicker.cpp \
src/ui/loadingscreen.cpp \
src/ui/unlockableicon.cpp \
src/config.cpp \
src/editor.cpp \
src/main.cpp \
@@ -268,6 +269,7 @@ HEADERS += include/core/advancemapparser.h \
include/ui/regionmappropertiesdialog.h \
include/ui/colorpicker.h \
include/ui/loadingscreen.h \
include/ui/unlockableicon.h \
include/config.h \
include/editor.h \
include/mainwindow.h \

View File

@@ -102,6 +102,7 @@
<file>images/Entities_16x16.png</file>
<file>images/pokemon_icon_placeholder.png</file>
<file>images/porysplash.gif</file>
<file>images/unlockable_tab_icon.dat</file>
<file>icons/clipboard.ico</file>
<file>icons/map_go.ico</file>
</qresource>

View File

@@ -0,0 +1 @@
<EFBFBD><EFBFBD>㻺<EFBFBD><EFBFBD><EFBFBD>߃<EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>\嫆<><E5AB86><EFBFBD><EFBFBD><EFBFBD>ߤ<EFBFBD><DFA4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۬<EFBFBD><DBAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݃<EFBFBD><DD83>ޭ<EFBFBD><DEAD><EFBFBD>޾<EFBFBD><DEBE><EFBFBD>ގ<EFBFBD><DE8E>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߦ<EFBFBD><DFA6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>غ<EFBFBD><D8BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺ<EFBFBD><DDBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޺<EFBFBD><DEBA>݋<EFBFBD><DD8B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޘ<EFBFBD><DE98><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܉ܧ<DC89><DCA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB>׵<EFBFBD><D7B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߄<EFBFBD><DF84><EFBFBD>ٙ<EFBFBD><D999><EFBFBD>ۊ<EFBFBD><DB8A><EFBFBD><EFBFBD><EFBFBD>؁<EFBFBD><D881><EFBFBD>֎<EFBFBD><D68E><EFBFBD><EFBFBD><EFBFBD>ׄ<EFBFBD><D784><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܆<EFBFBD><DC86>ݍ<EFBFBD><DD8D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĥ<EFBFBD>ە<EFBFBD><DB95><EFBFBD><EFBFBD><EFBFBD>֖<EFBFBD><D696><EFBFBD><EFBFBD><EFBFBD>Ċז<C48A><D796><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ګ<EFBFBD><DAAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ا<EFBFBD><D8A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߖ<EFBFBD><DF96><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڍ<EFBFBD><DA8D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٖ<EFBFBD><D996><EFBFBD><EFBFBD><EFBFBD>ۇ<EFBFBD><DB87><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>٤<EFBFBD><D9A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׾<EFBFBD>ډ<EFBFBD><DA89><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD>֚<EFBFBD><D69A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><D9B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>خ<EFBFBD>ޞ<EFBFBD><DE9E>ק<EFBFBD><D7A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD>ޝ۬<DE9D><DBAC><EFBFBD><EFBFBD><EFBFBD>ٚ<EFBFBD>ڞ<EFBFBD><DA9E>ޕ<EFBFBD><DE95><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>٣ש<D9A3><D7A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܌<EFBFBD><DC8C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޘ<EFBFBD><DE98><EFBFBD><EFBFBD>چ<EFBFBD><DA86>܊<EFBFBD><DC8A>܊<EFBFBD><DC8A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݋׿<DD8B><D7BF>֖ل<D696><D984>ץ<EFBFBD><D7A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ħ<EFBFBD><C4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>؆<EFBFBD>߮<EFBFBD><DFAE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڛ<EFBFBD><DA9B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۭ<EFBFBD><DBAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߊ<EFBFBD><DF8A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ێ<EFBFBD><DB8E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߇<EFBFBD><DF87><EFBFBD><EFBFBD><EFBFBD>ą<EFBFBD><C485><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׮<EFBFBD><D7AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߌ<EFBFBD><DF8C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD>ݠ<EFBFBD><DDA0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ס<EFBFBD><D7A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޿<EFBFBD><DEBF><EFBFBD><EFBFBD>Įĸ<C4AE><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶߞ<DCB6><DF9E><EFBFBD>Ĉ<EFBFBD><C488><EFBFBD>֫ֆ<D6AB>ܶ<EFBFBD><DCB6><EFBFBD>۪<EFBFBD><DBAA><EFBFBD>߈<EFBFBD><DF88><EFBFBD><EFBFBD><EFBFBD>߃<EFBFBD>߉<EFBFBD><DF89><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ފ<EFBFBD><DE8A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ւ<EFBFBD><D682><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۠<EFBFBD><DBA0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޾<EFBFBD>ؤ<EFBFBD><D8A4><EFBFBD><EFBFBD>ֿׂ<D782>Ī<EFBFBD><C4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>؍<EFBFBD><D88D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߚ<EFBFBD><DF9A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޘ<EFBFBD><DE98><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޢ<EFBFBD><DEA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڇ<EFBFBD><DA87>ֆ<EFBFBD><D686><EFBFBD>ۍ<EFBFBD><DB8D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޚݕ<DE9A><DD95><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>٭<EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܠ<EFBFBD><DCA0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޗ<EFBFBD>ڋ<EFBFBD><DA8B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>עĺ<D7A2>և<EFBFBD><D687><EFBFBD><EFBFBD>ڍ<EFBFBD><DA8D><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>ܪ<EFBFBD><DCAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ׈ڛ<D788><DA9B><EFBFBD><EFBFBD>ު<EFBFBD><DEAA>ٵ<EFBFBD><D9B5><EFBFBD>׬<EFBFBD><D7AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ښ<EFBFBD><DA9A>ݙڋ<DD99><DA8B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ي<EFBFBD><D98A><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD>ݩ<EFBFBD><DDA9><EFBFBD><EFBFBD><EFBFBD>ئ<EFBFBD><D8A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֞ۦ<D69E>ޟ<EFBFBD><DE9F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߪ<EFBFBD><DFAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܙ<EFBFBD><DC99><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ר<EFBFBD><D7A8>ޟ׸<DE9F><D7B8>ڟ<EFBFBD><DA9F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޛ<EFBFBD><DE9B><EFBFBD>؁<EFBFBD>؎<EFBFBD><D88E><EFBFBD><EFBFBD><EFBFBD>ګە<DAAB><DB95><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ħ<EFBFBD><C4A6><EFBFBD>Ĝ<EFBFBD><C49C><EFBFBD><EFBFBD>܍<EFBFBD><DC8D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ר<EFBFBD><D7A8><EFBFBD>܇<EFBFBD><DC87>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݇<EFBFBD><DD87><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ـ؊<D980><D88A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޶ۙ߮<DB99><DFAE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׈<EFBFBD><D788><EFBFBD>ݥ<EFBFBD>׌<EFBFBD><D78C>ٙ<EFBFBD><D999><EFBFBD><EFBFBD>ݟ݆<DD9F><DD86><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܸ<EFBFBD><DCB8><EFBFBD>ܞ<EFBFBD><DC9E><EFBFBD>܇<EFBFBD><DC87><EFBFBD><EFBFBD>č<EFBFBD>ە<EFBFBD><DB95><EFBFBD><EFBFBD>օ<EFBFBD><D685><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߎ<EFBFBD><DF8E><EFBFBD><EFBFBD><EFBFBD>ۇ<EFBFBD><DB87><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ہ<EFBFBD><DB81><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۂ<EFBFBD><DB82><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޹<EFBFBD><DEB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܅<EFBFBD><DC85><EFBFBD><EFBFBD>۵<EFBFBD><DBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׾<EFBFBD><D7BE>Ģ<EFBFBD>۝<EFBFBD><DB9D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޘ<EFBFBD><DE98><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ޘ<EFBFBD><DE98><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۧ<EFBFBD><DBA7>ۡۉ<DBA1>޹<EFBFBD><DEB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD><DCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۮ<EFBFBD><DBAE>י<EFBFBD><D799><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۞<EFBFBD><DB9E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ć<EFBFBD><C487>܁<EFBFBD><DC81><EFBFBD><EFBFBD>޵<EFBFBD><DEB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۼ<EFBFBD><DBBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܀<EFBFBD><DC80><EFBFBD><EFBFBD><EFBFBD>Ĩ<EFBFBD><C4A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݬ<EFBFBD><DDAC><EFBFBD><EFBFBD><EFBFBD>ݖ<EFBFBD><DD96>ܦ<EFBFBD><DCA6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>؅۟<D885><DB9F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>١׹<D9A1><D7B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܖ<EFBFBD><DC96><EFBFBD><EFBFBD>߿<EFBFBD>ݗ<EFBFBD><DD97><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD>ڸ٘<DAB8><D998><EFBFBD>ލ<EFBFBD><DE8D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>٠<EFBFBD><D9A0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֬<EFBFBD><D6AC>ܟ<EFBFBD><DC9F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻޘ<DABB><DE98><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ھ<EFBFBD><DABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׌<EFBFBD><D78C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>י<EFBFBD><D799>ދ<EFBFBD><DE8B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĩظٕ<D8B8><D995><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֝<EFBFBD><D69D>ו<EFBFBD><D795><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۜą<DB9C><C485>ܫ<EFBFBD><DCAB><EFBFBD><EFBFBD><EFBFBD>۷ؼ<DBB7><D8BC><EFBFBD>ڨ<EFBFBD><DAA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۟<EFBFBD><DB9F><EFBFBD><EFBFBD>۶<EFBFBD><DBB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׭<EFBFBD><D7AD>ݎ<EFBFBD><DD8E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׮<EFBFBD><D7AE><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD>ߘ<EFBFBD><DF98><EFBFBD>ی<EFBFBD><DB8C><EFBFBD>ā<EFBFBD>ׇ<EFBFBD><D787><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ę<EFBFBD><C499><EFBFBD>٪<EFBFBD><D9AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׫<EFBFBD>ެ<EFBFBD><DEAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߫<EFBFBD><DFAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݚ<EFBFBD><DD9A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٜ<EFBFBD><D99C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڮ<EFBFBD><DAAE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݫ<EFBFBD><DDAB>ي<EFBFBD><D98A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD>ٟ<EFBFBD><D99F>ڟ<EFBFBD><DA9F><EFBFBD>ޠڣߗ<DAA3>ێ<EFBFBD><DB8E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݧ<EFBFBD>ـ<EFBFBD>ق<EFBFBD><D982><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ي<EFBFBD><D98A><EFBFBD><EFBFBD>؞<EFBFBD><D89E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޻<EFBFBD><DEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD><DFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>٤<EFBFBD><D9A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ێ<EFBFBD><DB8E><EFBFBD><EFBFBD>ݞ<EFBFBD><DD9E><EFBFBD>؞<EFBFBD><D89E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ץ<EFBFBD><D7A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ć݃<C487><DD83><EFBFBD><EFBFBD>ݼ<EFBFBD><DDBC>ݙ<EFBFBD><DD99><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڄ<EFBFBD>م<EFBFBD><D985><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD>ݽפي<D7A4><D98A>޷<EFBFBD><DEB7><EFBFBD><EFBFBD>ޞٟ<DE9E><D99F><EFBFBD><EFBFBD>֥ا<D6A5><D8A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ט<EFBFBD>׼<EFBFBD><D7BC><EFBFBD>ޢ<EFBFBD>ܨ<EFBFBD><DCA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>և<EFBFBD><D687><EFBFBD><EFBFBD><EFBFBD>ڗ<EFBFBD><DA97><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݬ<EFBFBD>ܞ<EFBFBD><DC9E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>٩<EFBFBD><D9A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݠ<EFBFBD><DDA0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۛ<EFBFBD><DB9B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߜ<EFBFBD><DF9C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڪ<EFBFBD><DAAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ě<EFBFBD><C49B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٛ<EFBFBD><D99B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݬ<EFBFBD><DDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߊ׉<DF8A><D789><EFBFBD>׾<EFBFBD><D7BE><EFBFBD><EFBFBD><EFBFBD>ܟ<EFBFBD><DC9F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -334,6 +334,8 @@ void MainWindow::initCustomUI() {
ui->mainTabBar->setTabIcon(i, mainTabIcons.value(i));
}
this->unlockableMainTabIcon.load(":/images/unlockable_tab_icon.dat");
// Create map header data widget
this->mapHeaderForm = new MapHeaderForm();
ui->layout_HeaderData->addWidget(this->mapHeaderForm);
@@ -343,6 +345,12 @@ void MainWindow::initCustomUI() {
ui->graphicsView_Map->setResizeAnchor(QGraphicsView::ViewportAnchor::AnchorUnderMouse);
}
void MainWindow::overrideMainTabIcons(const QIcon& icon) {
for (int i = 1; i < ui->mainTabBar->count(); i++) {
ui->mainTabBar->setTabIcon(i, icon);
}
}
void MainWindow::initExtraSignals() {
connect(ui->tabWidget_EventType, &QTabWidget::currentChanged, this, &MainWindow::eventTabChanged);
@@ -2285,6 +2293,8 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index)
ui->stackedWidget_MapEvents->setCurrentIndex(1);
} else if (index == MainTab::Connections) {
ui->graphicsView_Connections->setFocus(); // Avoid opening tab with focus on something editable
connect(this, &MainWindow::mapOpened, this, &MainWindow::tryUnlockMainTabIcon, Qt::UniqueConnection);
connect(&this->unlockableMainTabIcon, &UnlockableIcon::unlocked, this, &MainWindow::overrideMainTabIcons, Qt::UniqueConnection);
}
if (!editor->map) return;
@@ -2294,6 +2304,18 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index)
}
}
void MainWindow::tryUnlockMainTabIcon(const Map* map) {
if (!map || this->unlockableMainTabIcon.isUnlocked()) return;
const Layout* layout = map->layout();
if (!layout) return;
QSet<QChar> chars;
if (!layout->name.isEmpty()) chars.insert(layout->name.at(0));
const QString tilesetName = Tileset::stripPrefix(layout->tileset_secondary_label);
if (!tilesetName.isEmpty()) chars.insert(tilesetName.at(0));
this->unlockableMainTabIcon.tryUnlock(chars);
}
void MainWindow::on_actionZoom_In_triggered() {
editor->scaleMapView(1);
}

178
src/ui/unlockableicon.cpp Normal file
View File

@@ -0,0 +1,178 @@
#include "unlockableicon.h"
#include <QFile>
#include <QBuffer>
#include <QRandomGenerator>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0))
constexpr int Version = QDataStream::Qt_6_8;
#endif
UnlockableIcon::UnlockableIcon(QObject* parent) : QObject(parent) {};
UnlockableIcon::UnlockableIcon(const QString& dataFilepath, QObject* parent) : UnlockableIcon(parent) {
load(dataFilepath);
};
#if (QT_VERSION < QT_VERSION_CHECK(6, 8, 0))
bool UnlockableIcon::createDataFile(const QString&, const QString&, const QString&) { return false; }
#else
bool UnlockableIcon::createDataFile(const QString& inputFilepath, const QString& outputFilepath, const QString& key) {
if (inputFilepath.isEmpty() || outputFilepath.isEmpty() || key.isEmpty()) return false;
if (key.length() >= std::numeric_limits<quint8>::max()) return false;
QByteArray key64 = key.toUtf8().toBase64();
if (key64.length() >= std::numeric_limits<quint8>::max()) return false;
QImage iconImage(inputFilepath);
if (iconImage.isNull()) return false;
QByteArray iconData;
QBuffer buffer(&iconData);
buffer.open(QIODevice::WriteOnly);
iconImage.save(&buffer, "PNG");
buffer.close();
if (iconData.length() >= std::numeric_limits<quint16>::max()) return false;
QByteArray iconData64 = iconData.toBase64();
if (iconData64.length() >= std::numeric_limits<quint16>::max()) return false;
QFile file(outputFilepath);
if (!file.open(QIODevice::WriteOnly)) return false;
QDataStream out(&file);
out.setVersion(Version);
quint8 r = QRandomGenerator::global()->bounded(std::numeric_limits<quint8>::max());
out << r;
out << static_cast<quint8>(key.length() ^ r);
out << static_cast<quint8>(key64.length() ^ r);
for (const auto& byte : key64) out << static_cast<quint8>(byte ^ r);
out << static_cast<quint16>(iconData.length() ^ (r | (r << 8)));
out << static_cast<quint16>(iconData64.length() ^ (r | (r << 8)));
for (const auto& byte : iconData64) out << static_cast<quint8>(byte ^ r);
file.close();
return true;
}
#endif
#if (QT_VERSION < QT_VERSION_CHECK(6, 8, 0))
bool UnlockableIcon::load(const QString&) { return false; }
#else
bool UnlockableIcon::load(const QString& dataFilepath) {
clear();
QFile file(dataFilepath);
if (!file.open(QIODevice::ReadOnly)) return false;
QDataStream in(&file);
in.setVersion(Version);
quint8 r = 0;
in >> r;
quint8 keyLength = 0;
in >> keyLength;
keyLength ^= r;
if (keyLength == 0) return false;
quint8 key64Length = 0;
in >> key64Length;
key64Length ^= r;
if (key64Length == 0) return false;
QByteArray key64(key64Length,0);
for (quint8 i = 0; i < key64Length; i++) {
in >> key64[i];
key64[i] ^= r;
}
QString key = QString(QByteArray::fromBase64(key64));
if (key.length() != keyLength) return false;
quint16 iconDataLength = 0;
in >> iconDataLength;
iconDataLength ^= (r | r << 8);
if (iconDataLength == 0) return false;
quint16 iconData64Length = 0;
in >> iconData64Length;
iconData64Length ^= (r | r << 8);
if (iconData64Length == 0) return false;
QByteArray iconData64(iconData64Length,0);
for (quint16 i = 0; i < iconData64Length; i++) {
in >> iconData64[i];
iconData64[i] ^= r;
}
QByteArray iconData = QByteArray::fromBase64(iconData64);
if (iconData.length() != iconDataLength) return false;
QPixmap iconPixmap;
iconPixmap.loadFromData(iconData);
if (iconPixmap.isNull()) return false;
m_icon = QIcon(iconPixmap);
m_key = key;
m_loaded = true;
return true;
}
#endif
void UnlockableIcon::clear() {
m_icon = QIcon();
m_key = QString();
m_keyIndex = 0;
m_loaded = false;
}
#if (QT_VERSION < QT_VERSION_CHECK(6, 8, 0))
bool UnlockableIcon::isUnlocked() const { return false; }
#else
bool UnlockableIcon::isUnlocked() const {
return m_loaded && m_keyIndex >= m_key.length();
}
#endif
#if (QT_VERSION < QT_VERSION_CHECK(6, 8, 0))
bool UnlockableIcon::canUnlock() const { return false; }
#else
bool UnlockableIcon::canUnlock() const {
return m_loaded && m_keyIndex < m_key.length();
}
#endif
QIcon UnlockableIcon::icon() const {
return isUnlocked() ? m_icon : QIcon();
}
#if (QT_VERSION < QT_VERSION_CHECK(6, 8, 0))
bool UnlockableIcon::tryKeyMatch(const QSet<QChar>&) { return false; }
#else
bool UnlockableIcon::tryKeyMatch(const QSet<QChar>& cSet) {
if (m_keyIndex >= m_key.length()) return false;
if (!cSet.contains(m_key.at(m_keyIndex))) {
m_keyIndex = 0;
return false;
}
if (++m_keyIndex == m_key.length()) {
emit unlocked(m_icon);
}
return true;
}
#endif
void UnlockableIcon::tryUnlock(const QSet<QChar>& cSet) {
if (canUnlock()) tryKeyMatch(cSet);
}
void UnlockableIcon::tryUnlock(const QChar& c) {
tryUnlock(QSet<QChar>{c});
}
void UnlockableIcon::tryUnlock(const QString& key) {
if (!canUnlock()) return;
for (const QChar& c : key) {
if (!tryKeyMatch(QSet<QChar>{c})) return;
}
}