mirror of
https://github.com/huderlem/porymap.git
synced 2026-03-21 17:45:44 -05:00
Add unlockable icon
This commit is contained in:
parent
dcef773a33
commit
df98d62339
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
57
include/ui/unlockableicon.h
Normal file
57
include/ui/unlockableicon.h
Normal 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
|
||||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
1
resources/images/unlockable_tab_icon.dat
Normal file
1
resources/images/unlockable_tab_icon.dat
Normal file
|
|
@ -0,0 +1 @@
|
|||
檴蒚<EFBFBD>遣<EFBFBD>𧒆葨輯\憳<><E686B3><EFBFBD>艉<EFBFBD><E88989>悅悅□<E68285>的<EFBFBD>悅<EFBFBD>悅悅菗恥悅悔鷉<E68294>氹悅<E6B0B9><E68285>姥猺尬管齒言<E9BD92><E8A880>舝<EFBFBD>鷼均播艀悅<E88980><E68285>答祤╮息Ⅰ䰾媞<E4B0BE><E5AA9E><EFBFBD><EFBFBD><EFBFBD>芳搡鼎<E690A1><E9BC8E><EFBFBD><EFBFBD>嗾尺<E597BE>陽<EFBFBD><E999BD><EFBFBD>憬<EFBFBD>妙毽<E5A699><E6AFBD><EFBFBD>漣拓<E6BCA3>完𡾞<E5AE8C>悍𡟺<E6828D><F0A19FBA>播<EFBFBD>譟<EFBFBD>㓤蹨<E393A4><E8B9A8>㒥<EFBFBD><E392A5>恕弩<E68195>𥥖知箕僈縧袢<E7B8A7><E8A2A2>𣶸<EFBFBD>㻛葍滬豪☆<E8B1AA><E29886>立<EFBFBD>𠱃<EFBFBD>𠶜<EFBFBD><F0A0B69C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㵢<EFBFBD><E3B5A2>⏛<EFBFBD><E28F9B>ㄚ𣺹<E3849A><F0A3BAB9>湗栀<E6B997><E6A080>谷弩撕艦㓈袿麾<E8A2BF><E9BABE>溢<EFBFBD>乖𠼱<E4B996>ˋ咱<CB8B>瓻<EFBFBD><E793BB><EFBFBD>𣽊尬<F0A3BD8A><E5B0AC><EFBFBD>撒秄往<E7A784><E5BE80>憤䬬<E686A4>襔蜈𣳿蛾<F0A3B3BF>嬰楹边<E6A5B9>襍<EFBFBD>㿗<EFBFBD>的𠗕扛平首蛹隄′䗩暀剏<E69A80><E5898F>𤤯撼<F0A4A4AF><E692BC>𡠺<EFBFBD>朱𧒆翔<F0A79286>枤硍螃<E7A18D><E89E83><EFBFBD>𧞅䠋<F0A79E85>車K<E8BB8A><EFBCAB><EFBFBD>齒堮␞<E5A0AE>=<EFBFBD><EFBC9D>擰<EFBFBD><E693B0>◎<EFBFBD><E2978E><EFBFBD><EFBFBD><EFBFBD>蔆詭鵞<E8A9AD><E9B59E><EFBFBD><EFBFBD>詣<EFBFBD>冤<EFBFBD>恩▼<E681A9>袿<EFBFBD><E8A2BF><EFBFBD><EFBFBD>燵𨑳鸌◢晻蚸<E699BB><E89AB8>蒈煖<E89288><E78596><EFBFBD><EFBFBD><EFBFBD>梳<EFBFBD><E6A2B3>L<EFBFBD>嵁飵㓁<E9A3B5>祣<EFBFBD><E7A5A3>罒縐寎鍈<E5AF8E>案左悅悅撩<E68285>瑤冀悄<E58680>儐<EFBFBD><E58490>藻<EFBFBD><E897BB><EFBFBD><EFBFBD>悅息佩<E681AF>蒏悅悌𥋘<E6828C><F0A58B98>陋<EFBFBD><E9998B>悅悅炤郎虞╳悅梴悅<E6A2B4><E68285>芝食<E88A9D>悅悅媡抅葷蝦須<E89DA6>爀<EFBFBD><E78880><EFBFBD>絳冥啹<E586A5>成夤纒雅悌<E99B85>梄限<E6A284><E99990>咯<EFBFBD><E592AF><EFBFBD>𤩐妙䊢<E5A699><E48AA2>䒏<EFBFBD>蛃<EFBFBD><E89B83><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>瓰<EFBFBD><E793B0>鳩冥泿<E586A5>ˊ<EFBFBD><CB8A><EFBFBD>馱皒鼎<E79A92><E9BC8E><EFBFBD><EFBFBD>弛<EFBFBD><E5BC9B>詅蛂<E8A985><E89B82><EFBFBD><EFBFBD><EFBFBD>瓡椚<E793A1>蠔譫<E8A094>抅㦛<E68A85><E3A69B>僆<EFBFBD><E58386>秺<EFBFBD><E7A7BA>眱<EFBFBD>廿馭<E5BBBF>菄<EFBFBD>渘<EFBFBD>擀<EFBFBD><E69380>猷黇<E78CB7><E9BB87>𨯙K<F0A8AF99><EFBCAB>𥶹<EFBFBD><F0A5B6B9>贜<EFBFBD><E8B49C><EFBFBD><EFBFBD>限<EFBFBD><E99990>腺<EFBFBD>幼M嵗爰鱝疙鮗<E79699>堣<EFBFBD>爾<EFBFBD>祪珀炒擘𠘑≦<F0A09891><E289A6>凝悅<E5879D>䌫蓿𥋘𥣞賓<F0A5A39E>涱<EFBFBD>飧<EFBFBD><E9A3A7><EFBFBD>𢆡<EFBFBD>悅狙凳膘˙<E88698>葵煍<E891B5><E7858D>㭻<EFBFBD>筐<EFBFBD>絳窙㭘悅憐<E68285>塽<EFBFBD><E5A1BD><EFBFBD><EFBFBD><EFBFBD>倍<EFBFBD>𩜠郎萰<E9838E>疚𦹄<E7969A>欿<EFBFBD>ǜ<EFBFBD>𤀑<EFBFBD>芳㜃権<E39C83><E6A8A9>𨑳◎楈〢<E6A588><E380A2>撮<EFBFBD><E692AE><EFBFBD><EFBFBD>癎階靰<E99A8E><E99DB0><EFBFBD><EFBFBD><EFBFBD>貍勌舝<E58B8C><E8889D><EFBFBD>ㄗ猼煨棫祣痈<E7A5A3><E79788>𪇵<EFBFBD><F0AA87B5><EFBFBD><EFBFBD>袤<EFBFBD>癍<EFBFBD><E7998D>豑𡠺<E8B191><F0A1A0BA>稌<EFBFBD>栀<EFBFBD>僊<EFBFBD><E5838A>搣<EFBFBD><E690A3>倃<EFBFBD>遜<EFBFBD><E9819C><EFBFBD>𩷶╲<F0A9B7B6><E295B2>萓濯<E89093><E6BFAF>𧚔鿋盲末<E79BB2><E69CAB><EFBFBD>𣫺甅菁<E79485>管㗾腦稄<E885A6><E7A884><EFBFBD>俤<EFBFBD>蛹<EFBFBD>䦉緒𧦠<E7B792>瓻<EFBFBD>鵭<EFBFBD>舚䊢汙榀<E6B199><E6A680>𠯫<EFBFBD><F0A0AFAB>帕縉<E5B895>险<EFBFBD><E999A9><EFBFBD>尌<EFBFBD><E5B08C><EFBFBD><EFBFBD>楰𨯙睎<F0A8AF99><E79D8E>稱腄𤣩〞<F0A4A3A9><E3809E><EFBFBD><EFBFBD><EFBFBD>妨<EFBFBD>僩樑<E583A9><E6A891>楞<EFBFBD><E6A59E><EFBFBD>瑗<EFBFBD>蒏<EFBFBD><E8928F><EFBFBD>㵯⏚拐搘尤<E69098>夥<EFBFBD><E5A4A5>櫊<EFBFBD><E6AB8A><EFBFBD>抿棌<E68ABF>戍概<E6888D>楃𦜖<E6A583>殤葦<E6AEA4><E891A6><EFBFBD>豌<EFBFBD>𤜯矬㨃<E79FAC>倍鰟<E5808D><E9B09F>筑挪■ㄒ<E296A0>稃<EFBFBD><E7A883><EFBFBD>歒瑌<E6AD92>爾石<E788BE><E79FB3><EFBFBD><EFBFBD><EFBFBD>朴石<E69CB4>防防<E998B2><E998B2>井<EFBFBD><E4BA95><EFBFBD>龟穴<E9BE9F>袐<EFBFBD><E8A290><EFBFBD><EFBFBD>詘<EFBFBD><E8A998>㿗<EFBFBD><E3BF97>㚰鸘市<E9B898>左硉<E5B7A6><E7A189><EFBFBD>窖<EFBFBD>論<EFBFBD>乖K<E4B996>飩黾<E9A3A9><E9BBBE>誹<EFBFBD><E8AAB9><EFBFBD><EFBFBD>齒櫊<E9BD92><E6AB8A><EFBFBD>僮邑鮗<E98291>埯<EFBFBD>𨀉坐<F0A88089>∞䳍瑐蒄<E79190>舅欿陽溶劃誠<E58A83><E8AAA0>蔐<EFBFBD>葭𧇍<E891AD>䤆<EFBFBD><E4A486>ㄗ<EFBFBD><E38497><EFBFBD><EFBFBD><EFBFBD>ˋ𧋦<CB8B>𤀑<EFBFBD><F0A48091>石瑑‵<E79191>羲䣳∞蛩<E2889E>𠶖<EFBFBD>策椽<E7AD96><E6A4BD><EFBFBD>矬<EFBFBD>𤨓<EFBFBD><F0A4A893><EFBFBD><EFBFBD>Ⅰ<EFBFBD>搰<EFBFBD>㑳萫𢜟葄成<E89184><E68890>煥<EFBFBD><E785A5>ㄝ<EFBFBD>萳=劂疝ㄜ𧊅<E3849C><F0A78A85><EFBFBD>葵櫊丑𧊋<E4B891><F0A78A8B>尾萷嵋𠳿<E5B58B><F0A0B3BF>嚏涤<E59A8F><E6B6A4>M皒<EFBCAD>楤技<E6A5A4><E68A80><EFBFBD>蔚<EFBFBD><E8949A><EFBFBD>障阸食<E998B8><E9A39F><EFBFBD><EFBFBD>眲‵<E79CB2>㜜祣<E39C9C>僱<EFBFBD>央憚㨪靼<E3A8AA>㚹<EFBFBD><E39AB9>憐睅<E68690><E79D85>躀俤<E8BA80><E4BFA4>礶𤄙<E7A4B6><F0A48499>楨<EFBFBD>ㄨ鸘<E384A8>漱<EFBFBD>𤜯╯<F0A49CAF>蘑婺<E89891>夾剳<E5A4BE>楺𠹭皿<F0A0B9AD><E79ABF>漫擘<E6BCAB><E69398>鱓鮟<E9B193>葾𧡘<E891BE>軞<EFBFBD><E8BB9E>妨蛪媦龬矢酉𢞁<E98589>尼汝絍<E6B19D>膚<EFBFBD><E8869A>罹蛚𣱣𦋐苸𧗾脃撬蚼<E692AC><E89ABC>丹𤪓聛玏悅<E78E8F>撩蔬鼓<E894AC><E9BC93>階<EFBFBD><E99A8E>洵䐭氈儷捏䲰僊犒𤽜<E78A92>墚<EFBFBD>◥裗<E297A5><E8A397><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𦋐傈炙咿限菁囿猻”儐楊慰葖焩<E89196><E784A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>撫縐<E692AB><E7B890><EFBFBD><EFBFBD>煆恩<E78586>丰<EFBFBD>㭘巨𤨪<E5B7A8>搦<EFBFBD><E690A6>井<EFBFBD>礶<EFBFBD><E7A4B6>璍<EFBFBD><E7928D>汝袧桓𦴣L<F0A6B4A3><EFBCAC>穴㷛␟僴<E2909F><E583B4><EFBFBD>𥅾<EFBFBD>搷戒<E690B7>棇<EFBFBD><E6A387>𪃳<EFBFBD><F0AA83B3><EFBFBD>𦾾<EFBFBD>弩䰻<E5BCA9>帑軜遙<E8BB9C><E98199>菌<EFBFBD><E88F8C>漱縈<E6BCB1>搇暀蝙<E69A80><E89D99><EFBFBD>衮<EFBFBD><E8A1AE><EFBFBD>椘<EFBFBD>岡銾墚蕊<E5A29A><E8958A><EFBFBD><EFBFBD>蚰<EFBFBD>悟愇籰黆<E7B1B0>巍<EFBFBD><E5B78D><EFBFBD><EFBFBD>敯<EFBFBD><E695AF>◣<EFBFBD>愇<EFBFBD>詀<EFBFBD><E8A980><EFBFBD><EFBFBD>雁秣斒蚺<E69692><E89ABA>瑀誧岷<E8AAA7><E5B2B7><EFBFBD><EFBFBD>皏塈<E79A8F>帖<EFBFBD><E5B896>𥐙𤽜袧<F0A4BD9C><E8A2A7>煍濤<E7858D>岱<EFBFBD>泿<EFBFBD>蕃㽼<E89583><E3BDBC><EFBFBD><EFBFBD>秄<EFBFBD>𣇪心笣眉<E7ACA3><E79C89><EFBFBD><EFBFBD>息<EFBFBD>遞飵<E9819E><E9A3B5>㷫<EFBFBD>遘壕<E98198>閂<EFBFBD>𡆀狎<F0A18680><E78B8E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>葾𤌍悅<F0A48C8D><E68285><EFBFBD>嫦𧊋<E5ABA6>袿<EFBFBD><E8A2BF><EFBFBD>漁<EFBFBD>𥺁蛻<F0A5BA81>琲<EFBFBD>岷噢<E5B2B7><E599A2>婹坾<E5A9B9><E59DBE><EFBFBD>𡠠<EFBFBD>重<EFBFBD><E9878D><EFBFBD>␝<EFBFBD>孺<EFBFBD>僱<EFBFBD><E583B1><EFBFBD>蕨<EFBFBD><E895A8><EFBFBD><EFBFBD>彍<EFBFBD><E5BD8D>㗲崵𠼱<E5B4B5>擦袛冀𤊄𪷿叚嶽悅悅<E68285>彿<EFBFBD>𠗕<EFBFBD><F0A09795>
|
||||
|
|
@ -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
178
src/ui/unlockableicon.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user