From b247af535df666b47511c05ad7bb28e83b704790 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 9 Sep 2020 23:44:21 +1000 Subject: [PATCH] Qt: Hook up cheat list menus --- src/duckstation-qt/generalsettingswidget.cpp | 4 +- src/duckstation-qt/generalsettingswidget.ui | 7 ++ src/duckstation-qt/mainwindow.cpp | 10 +++ src/duckstation-qt/mainwindow.h | 1 + src/duckstation-qt/mainwindow.ui | 21 +++++ src/duckstation-qt/qthostinterface.cpp | 83 ++++++++++++++++++ src/duckstation-qt/qthostinterface.h | 6 ++ .../icons/actions-tools-wizard-32.png | Bin 0 -> 2122 bytes .../icons/actions-tools-wizard-32@2x.png | Bin 0 -> 5960 bytes .../resources/icons/actions-tools-wizard.png | Bin 0 -> 762 bytes .../icons/actions-tools-wizard@2x.png | Bin 0 -> 2122 bytes src/duckstation-qt/resources/resources.qrc | 4 + 12 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/duckstation-qt/resources/icons/actions-tools-wizard-32.png create mode 100644 src/duckstation-qt/resources/icons/actions-tools-wizard-32@2x.png create mode 100644 src/duckstation-qt/resources/icons/actions-tools-wizard.png create mode 100644 src/duckstation-qt/resources/icons/actions-tools-wizard@2x.png diff --git a/src/duckstation-qt/generalsettingswidget.cpp b/src/duckstation-qt/generalsettingswidget.cpp index efe38d487..d6c0b53e6 100644 --- a/src/duckstation-qt/generalsettingswidget.cpp +++ b/src/duckstation-qt/generalsettingswidget.cpp @@ -25,6 +25,8 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW "LoadDevicesFromSaveStates", false); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.applyGameSettings, "Main", "ApplyGameSettings", true); + SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.autoLoadCheats, "Main", "AutoLoadCheats", + false); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showOSDMessages, "Display", "ShowOSDMessages", true); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showFPS, "Display", "ShowFPS", false); @@ -104,7 +106,7 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW "to use XInput over SDL2 for compatibility.")); // Since this one is compile-time selected, we don't put it in the .ui file. - int current_col = 1; + int current_col = 0; int current_row = m_ui.formLayout_4->rowCount() - current_col; #ifdef WITH_DISCORD_PRESENCE { diff --git a/src/duckstation-qt/generalsettingswidget.ui b/src/duckstation-qt/generalsettingswidget.ui index 9d3b09b68..6c10f087a 100644 --- a/src/duckstation-qt/generalsettingswidget.ui +++ b/src/duckstation-qt/generalsettingswidget.ui @@ -81,6 +81,13 @@ + + + + Automatically Load Cheats + + + diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 756951b0f..ebd7c3a1a 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -306,6 +306,12 @@ void MainWindow::onChangeDiscFromPlaylistMenuAboutToHide() m_ui.menuChangeDiscFromPlaylist->clear(); } +void MainWindow::onCheatsMenuAboutToShow() +{ + m_ui.menuCheats->clear(); + m_host_interface->populateCheatsMenu(m_ui.menuCheats); +} + void MainWindow::onRemoveDiscActionTriggered() { m_host_interface->changeDisc(QString()); @@ -545,9 +551,11 @@ void MainWindow::updateEmulationActions(bool starting, bool running) m_ui.actionReset->setDisabled(starting || !running); m_ui.actionPause->setDisabled(starting || !running); m_ui.actionChangeDisc->setDisabled(starting || !running); + m_ui.actionCheats->setDisabled(starting || !running); m_ui.actionScreenshot->setDisabled(starting || !running); m_ui.actionViewSystemDisplay->setEnabled(starting || running); m_ui.menuChangeDisc->setDisabled(starting || !running); + m_ui.menuCheats->setDisabled(starting || !running); m_ui.actionSaveState->setDisabled(starting || !running); m_ui.menuSaveState->setDisabled(starting || !running); @@ -622,6 +630,8 @@ void MainWindow::connectSignals() &MainWindow::onChangeDiscFromPlaylistMenuAboutToShow); connect(m_ui.menuChangeDiscFromPlaylist, &QMenu::aboutToHide, this, &MainWindow::onChangeDiscFromPlaylistMenuAboutToHide); + connect(m_ui.menuCheats, &QMenu::aboutToShow, this, &MainWindow::onCheatsMenuAboutToShow); + connect(m_ui.actionCheats, &QAction::triggered, [this] { m_ui.menuCheats->exec(QCursor::pos()); }); connect(m_ui.actionRemoveDisc, &QAction::triggered, this, &MainWindow::onRemoveDiscActionTriggered); connect(m_ui.actionAddGameDirectory, &QAction::triggered, [this]() { getSettingsDialog()->getGameListSettingsWidget()->addSearchDirectory(this); }); diff --git a/src/duckstation-qt/mainwindow.h b/src/duckstation-qt/mainwindow.h index e53053866..3fdfcc7a4 100644 --- a/src/duckstation-qt/mainwindow.h +++ b/src/duckstation-qt/mainwindow.h @@ -61,6 +61,7 @@ private Q_SLOTS: void onChangeDiscFromGameListActionTriggered(); void onChangeDiscFromPlaylistMenuAboutToShow(); void onChangeDiscFromPlaylistMenuAboutToHide(); + void onCheatsMenuAboutToShow(); void onRemoveDiscActionTriggered(); void onViewToolbarActionToggled(bool checked); void onViewStatusBarActionToggled(bool checked); diff --git a/src/duckstation-qt/mainwindow.ui b/src/duckstation-qt/mainwindow.ui index 14e80ffee..5e47ee565 100644 --- a/src/duckstation-qt/mainwindow.ui +++ b/src/duckstation-qt/mainwindow.ui @@ -55,6 +55,15 @@ + + + Cheats + + + + :/icons/actions-tools-wizard.png:/icons/actions-tools-wizard.png + + Load State @@ -82,6 +91,8 @@ + + @@ -203,6 +214,7 @@ + @@ -385,6 +397,15 @@ Change Disc... + + + + :/icons/actions-tools-wizard-32.png:/icons/actions-tools-wizard-32.png + + + Cheats... + + diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index ddacf57e3..d2a15eb18 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -5,6 +5,7 @@ #include "common/file_system.h" #include "common/log.h" #include "common/string_util.h" +#include "core/cheats.h" #include "core/controller.h" #include "core/gpu.h" #include "core/system.h" @@ -27,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -952,6 +954,87 @@ void QtHostInterface::populatePlaylistEntryMenu(QMenu* menu) } } +void QtHostInterface::populateCheatsMenu(QMenu* menu) +{ + Assert(!isOnWorkerThread()); + if (!System::IsValid()) + return; + + const bool has_cheat_list = System::HasCheatList(); + + QAction* action = menu->addAction(tr("&Load Cheats...")); + connect(action, &QAction::triggered, [this]() { + QString filename = QFileDialog::getOpenFileName(m_main_window, tr("Select Cheat File"), QString(), + tr("PCSXR/Libretro Cheat Files (*.cht);;All Files (*.*)")); + if (!filename.isEmpty()) + loadCheatList(filename); + }); + + action = menu->addAction(tr("&Save Cheats...")); + action->setEnabled(has_cheat_list); + connect(action, &QAction::triggered, [this]() { + QString filename = QFileDialog::getSaveFileName(m_main_window, tr("Select Cheat File"), QString(), + tr("PCSXR/Libretro Cheat Files (*.cht);;All Files (*.*)")); + if (!filename.isEmpty()) + SaveCheatList(filename.toUtf8().constData()); + }); + + QMenu* enabled_menu = menu->addMenu(tr("&Enabled Cheats")); + enabled_menu->setEnabled(has_cheat_list); + QMenu* apply_menu = menu->addMenu(tr("&Apply Cheats")); + apply_menu->setEnabled(has_cheat_list); + if (has_cheat_list) + { + CheatList* cl = System::GetCheatList(); + for (u32 i = 0; i < cl->GetCodeCount(); i++) + { + CheatCode& cc = cl->GetCode(i); + QString desc(QString::fromStdString(cc.description)); + action = enabled_menu->addAction(desc); + action->setCheckable(true); + action->setChecked(cc.enabled); + connect(action, &QAction::toggled, [this, i](bool enabled) { setCheatEnabled(i, enabled); }); + + action = apply_menu->addAction(desc); + connect(action, &QAction::triggered, [this, i]() { applyCheat(i); }); + } + } +} + +void QtHostInterface::loadCheatList(const QString& filename) +{ + if (!isOnWorkerThread()) + { + QMetaObject::invokeMethod(this, "loadCheatList", Qt::QueuedConnection, Q_ARG(const QString&, filename)); + return; + } + + LoadCheatList(filename.toUtf8().constData()); +} + +void QtHostInterface::setCheatEnabled(quint32 index, bool enabled) +{ + if (!isOnWorkerThread()) + { + QMetaObject::invokeMethod(this, "setCheatEnabled", Qt::QueuedConnection, Q_ARG(quint32, index), + Q_ARG(bool, enabled)); + return; + } + + SetCheatCodeState(index, enabled, g_settings.auto_load_cheats); +} + +void QtHostInterface::applyCheat(u32 index) +{ + if (!isOnWorkerThread()) + { + QMetaObject::invokeMethod(this, "applyCheat", Qt::QueuedConnection, Q_ARG(quint32, index)); + return; + } + + ApplyCheatCode(index); +} + void QtHostInterface::loadState(const QString& filename) { if (!isOnWorkerThread()) diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h index 663bb26eb..0d5c48721 100644 --- a/src/duckstation-qt/qthostinterface.h +++ b/src/duckstation-qt/qthostinterface.h @@ -90,6 +90,9 @@ public: /// Fills menu with the current playlist entries. The disc index is marked as checked. void populatePlaylistEntryMenu(QMenu* menu); + /// Fills menu with the current cheat options. + void populateCheatsMenu(QMenu* menu); + ALWAYS_INLINE QString getSavePathForInputProfile(const QString& name) const { return QString::fromStdString(GetSavePathForInputProfile(name.toUtf8().constData())); @@ -158,6 +161,9 @@ public Q_SLOTS: void saveScreenshot(); void redrawDisplayWindow(); void toggleFullscreen(); + void loadCheatList(const QString& filename); + void setCheatEnabled(quint32 index, bool enabled); + void applyCheat(quint32 index); private Q_SLOTS: void doStopThread(); diff --git a/src/duckstation-qt/resources/icons/actions-tools-wizard-32.png b/src/duckstation-qt/resources/icons/actions-tools-wizard-32.png new file mode 100644 index 0000000000000000000000000000000000000000..34e4a79ba16d31663ee7ec4b3bab34e99ed40229 GIT binary patch literal 2122 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 AdjJ3c literal 0 HcmV?d00001 diff --git a/src/duckstation-qt/resources/icons/actions-tools-wizard-32@2x.png b/src/duckstation-qt/resources/icons/actions-tools-wizard-32@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe9a333dd81c398836792603a36a2bea87d4829 GIT binary patch literal 5960 zcmV-O7q{q%P)=w3gI};?sB;p zi^Vd?X0v7A>72ZSe@hO~M-A1e1<{0t$m1x@aeJIqsZSs0?|T4H z@wWv6!8EyC?sYgE0<~H#t*EE~p-{Nm?RHPRb$-F8!&#xO=c<^*N5?U|1AuD*;9Gd` z)ZwV$fbjs>?O7)?6&Uaz-jFJ!!Gj9I!b&XZrn@)AOqXker;X#vRuSSVoqAHn*;! zvFSaxmwT@Dx-l^^U^bhfzP`RmsZ@qotybra=O0}ZG^*Fomo_lU2o^Xy?l1!2s^p+% zr4v{?fDo<^UL*q$sTdFn7>CPTe=OI&OCS<$QYd9-yANu# zob*nvOhz5Uf<(!Hw}AssB@Y7bCgpL6uMIo~9RBt4Lhyi4!Ck5dIaFBGIDhz?S-8!dB=T1yW zXqejRbSNq=$_4vLG5xw5jdsIghQ34upqSjQ5;8_1(X+k9kLD{-xC1W&mn4lN2mKBRWwt zTEPkgVBU?#d&e6jCQw8)n=NAWVcu;qGEYY^T|(vjZ&USEA2eMB( zgM))3CQh9AQUCt^!QbECH!vdr1w+h;Z$A0tlXGu(AG1b*Kq3Z4rvYyA3iyFL&K?f} zHwR%13(pQphY4}95TpwN30j8~0bs}-c-8Cfv#00m%r7vE`R_j!d+xynx(*6@|Lp#n zXBR zSRNz3J|!guUV7;z7&2rCr8}sqs)CCbFHXViFd`rz00;yc$O-6oKr0&h*kg}<`E%~; zy4Ab@DS!GMY&94l661mhl)u4Dp|_V`U3+fNzL50E(=U7O8G!s(RE*mr=oiA6Ulw_} zCrga1d0Qd(&vgZ`#m>lVJ$v?qqM{=5Yi`7d5qjKphIScu9&mTTZnr~0K|um$hNVG4 zK|bXJ0|P-Kkw9f-CB=eGPdxF&bH4-tB=cT@IrhqVJU;13Y+9)?YU zm-ilTS@^-1znMAD_H~;8FfWpJ61bepEe`Qx3@dkiQ2_r~bWF6QptR1WkqaG0yC)c@ zu^l^hgk{T?LAP$*0GS<>l$40->gqyqr|qq#-f9J>PoEx-Y4Z1!4F~|T0)}BI4#4^I z=SN{S*wL1IYm3Z(1>TtbieWCOM+3NzdU&{Eo4>ezO*zx`1F_>a^gzQz6qc(@r2 zZk?#8nmajtTf=K7%K3t>UAqD*M?TF*_)Asu2gc0mFlE_?8hxmXb`yz^kNluA2Ha6M zD(N8rNLjK1NH#VSdvpuNeSGLsOFHj2kV3l0P3u4pGp^_4Gg;?C-S~`c6rFekF4;(&x zcrkuXs;#Ys{QP{Mbx<}~zI=I8@6?pw{aHs`KNo;S)5T*lCue-jh>(`F>?RUr+mi)f zHZ-xn9Y2HPZVLdnUDJoL8+U;sRtu6)Tgl}s!xrvoI=t$DIRFo{t@F~;(_zuP*%HIq z&5K2q=SJSNNXI^($VR_2pIjj~H#Zvp@(6;BKp=Cc)VONZs*HsT7tSRPKvpwyBBtpLVh8Fl7z<73Z@mLJa4o?!#k^B$f7lnLvwxr0QY&| zQ;fs34OEE|kjL=erb|PGBXhr^V}5d>)NJ?o(|Hu^HVluR8`@Gf8hBoL;~HL>`l@a8 zvfpTfBOGMb=qi%4XU`^JHmF1ZxT{yM0`2;#Q>TP$SFhYAWO%hg#KMq%=`biG4T{g@ z!hyrtyAGGxM*I}Tzg?~uSZz(O4ILOWkJUUP0MmL@o&%c;oby-1%-CpHHvTWb{{R5b zm%6^J+x|5pYcBBm#~8lPP=gq?w%5JyK2syIS|rxAw!w}#Z-Z@;*lHYxcq{1 z8%Mr7Mx)XCTm_3FQr56{?_SwwpMBQU*x2Z!!Nd`EtX}-Gx9-YQ611y`h%o4t-Uozo zKUlMQyNg%qg0u53HrlW4!eu>(;H)8Vm*rnXR8n3F>Xr_prvw zZa2=UOPlZloABsSGIuJ9wrtrVoIZVeSEtiii_zZIr%xXkI&>&hT+EL@v~%M!3ldY2 zLJj=~KLLr|Qeo@%9Z*_Q{9K(kLc+Op_J?p&pWr$G#_!U1`+EzAfx0(R#zb&56mFLF**^Mq7u&jZD}zeuFuhSz z1M~+LZWJ|KjhBv^{k%)2t*$toHK17;QY1ITUp;>OI2=2640`nF0Xuf=2tRo6U;xka zRY-+>RuCT_53jxU+Q%3a!^l#IE)NYL+P68fF`AkvT zjsqtd_~>9YZWm%^m#TrJ3A87nHkd>9~Bh^!-frm@bGZq zJMX-c)YR0}jLJ46*@1xr2Ligr7zAbdlEZB0i0A~JkKUCgH4<7(EXI@{aQ#mHG^wrsj z!N3F7=K9~OGWKryG2{^hIp%cg`uK{P*5U@u941emEXN&ehto(|Ad??Fcre9+h%dhQ zLXUGQBO@a{+g34Aa8z7fa|klp-2y8Bs>;R zjb`y{y1t*hcQ^C<^wUrMu$ohlE6~kTv4i>Dm+LXjwZq-Ry8|oj=;Mz+4habfqLnLG zCSmF8#8g;AR?xR^Us$?y>5}T|>Mj&7GBPrJu0Wh%(}s^Pzt~gQAzW%Sq=b1#Yn0q` z5kaC(posuRBEzjN!5g*%Cze6AU1(gk*Z!` z_y+t*4ZO4ynB0*^y}Y2G?vXX_yDjp`rVU#Ez#s|j7%Bp(si}Y!9cD+K#qUuV^{Iq* zP<=pFP+D4QK-XwzG#VS)w{LHuN)ZXu(A~RtXVQB3o3DBd(`%vn(0X__yey}e0g@P{ znq@FUfDqlZr5qUv2b@#|H7-Tdx-9dGvIggeT?}m9)Q{Y4?hyMdp!D3v_vJ00Pt!Vf z0P97I5rzQI>YVT_XjJQ$B9F=hnCnfU}3*j#No3Cj!NV zI;HI^VBFM#mI2Rbz~l-$Q`M|qY&F&I>h(gd?RJY)WOiG7q0UzJ)YgkD9Ue+N02JjZ zz;*B59d_;76@28#5tYm3GGZX)==X+(hN#jDx$X6gHE2kLEGQ#f+)?W&@8K`?ib2RA z7m$HaDnu)CfZOXr5{9}d{J^COf%6S;ao4Gue^eSB>yskIO;b0Sf6_C7>j01}fBV^f zkEOTU8LD;qD;(LtS}q{s9PnO59*4)pTF+M~vRlm7)1nq>fvH|u8msiHl<>lF0*3jk z&F#%vai(_gf+KZAml+IvOmcFvU{IePs!+8s`oxig2@0<@I3_@*>=i0+A18Nol-rtg z&{)GT9xt${v=^bXQ?Y@UWO3JpG7+%q090BJc1C3TJg;f@mCBk8$gB=5_@?=1*9kWP zKr-zQT@w1Ig{Jt0*sv4Y5!2aLG@z1Q@8`xOW8Wx!Ho09TX$O$+e^Q!roZWi1Mu z(<4Xs6f<64D8Z;EVGts>2OP#mU|Ve9kBTzrX`BbMF1jm^>yp`!savHOgET?FY1)C2 zRlsGpKODJif_1wO?H-mKG-B1iN`6+m>_-70nKda{WHZ-{9?~~@YI2v(N&e~pM$9z> zV=o29R)t$s2b{?Wru-=2T;kg-iBL$(z|9+dfH7Eai3MU1u_B+MEjA}ey>3ua>Js?_ zC(&Tg)q)p?gAwt$RYv=symG~%!b%W?#zW7vM|^z(j2X^gjV$CuUeP^K<9i06Rc4Hj z6WYv;i5i7>WJ*GKza9x;-Tc(;q%ye(`GSrux|ArAwD4)zs9i`hNl7MtSqaI6*~Ci$p1I=`3eFQPKYLKEsr{Dd4@ioIbD7 zp0@_-T8Z4xX!nY0a|*8VCyQ%KyaH)8#t9ble}co| zV9aK-r&q6Dm04L?AKC5pFsdY}!lxaO)9uG5o=gyrWEiH|jDB+j_6-b6W zF)=Ze9-~p=K?@Kj;=+@6R!}9#jt<>exBpF4tVb6Ulo8`rRJ5yP>yG2 zUTSv!x$pYIo1(K=$VglsUPITSCJ6NlV`F1Q`T6-#_4V~Ek|ZZ`02eBsNOQ0#;?d;U z)2C1WoxW4gkgR~*;QaaX)H!+s&zbj=ZuI{OfHnvp@8|9}07&TO)V>dLIlU?)#ho=!uB4cNMNOgA{ zpvf=B;Hac|1ONd+JqH9~2c9#E*0?&Q3#$+dsQ#xEI`_Mhg(5E4UDl(fGYT(P3(r(V!riot^FUQ^-QfDyx0e7Wh$@eP&Boq&P1w~L$5Q94&g=tTWE+I$XkHw%!<+lN2!C!on0|I=pfSw=`CvceR zCsi~wuR8X8CrOM(N~Yfamh~qh0ITn30H^~Sh(ka-jHE|~aUlYMpmzsjaHo}M1vX5R zZ=q%ADP|Beq-=mG6wc-5WY5ZocxFsT*>a2vzcrtWO{$Aqcna5#A2~kVxTs zqQs!@vwnVlQOFoY806Yx094`d$2c&Dj#Cz(%t73M-aHF*H@-KqThM1|!IA`>T(saC zm?WR$pqil`$6^HFw!O{!1ppGF%D!ieXzB_CAq>NT3gdx~_96|Qf^HB+{GmgK4!&$a z)HpxyY_ZGj@y#iFDRGue#J-Im_n^X0wdJDs696P+`eY4M{RJZkYO4MS7-WlS=n~J+ zF{0800)dg2mj^N-^GKc1{O|0sox)=Sq=h)84+4<$AOb-5LncgdL4a8x3iH1PL1>Rb zQies)8+42cB#Hx+KB=?ZP+z~&;dJ__F>(S$ zXa!?&P}%Iu1mp(vq6MbJ#sIZ4q`_plXKH*u0zg7flQh@vFBG#vC}xNl{G5Pp@I1Xz zN5PO@!6nLESXfA}*^NMOc0DWrkPu5GwkSmNk3wz`hsye4P@IeWKta60U@-WeN7Czc z$P0F0kR0_e0YK8)Lr|l_9T9{W%>N@%(R8B2q&&F-Rft$RJMnlh0%W|G3*7GjkhId} zaEt>fXa#X-?o){fQ5Faf5BI%fNqqtYW+DQ!`d$`)5CCYU%ak6IQ0ewKX3=jH3tHbi zqt+Vof@}n)_q{CsAOJu@T_myu>Lc_;cNmT!45kB=66uv&q{~oUT}_RY_Gk$u4;ug^ z6bmROP|4c|L70UgPz%9l1>^?wx*f_~w1PJuMgT}CD^PlT9LKAa9ViY^vy@)QptsL3 z2wuWtu@5T%B;*G1IHuxwhAe=%0I@>k0n}HdIrQ4zzaLfrC@50*=vf@^!}mPFM~tXn z(A4B>5Yh9)Ne?RkBvdOlZPN34t*8fPsl<38*@an#O``&NM0uM9*z8na!04v7d qA|LQzZEzAnc=zz(!)@vXko*rutMSNd6)VO70000GhXyjPDPhx+T)<6Z!l!+<=!wdU0!SzFfNR z8MFVJ7cYghtQ{HDtUL?cJUoSWteq))V*5ntf6NSj*|-@5VuKmto!n)!*6#l84maRk z8%Owpqbv%`uCkpeXqog{S65dQDC{pPDw;cQ-aOBmnwlNR-n+hEW&P(r>^B&vWpgrT zxQNZ3vgPm6WoHE*&UF!9CS((``kBeISFN(N(WbJr6udz^m&B>d;uU)$) zCN3@}DaG=`!&K~do|p8aE21(SdigG&?-}_Xa>-via`uAd(K}!NAcqA!5G}NMSbD6b zon*N<)w`~JIlAZS8#aD%d4{(izleYQ_%Xx4z`*6ysZ%naK7D$L)c`DjMMy|UOh70dm-oz6_|X-mB_O%;?#I%YjrU&>V*m&Ub8>P< z1MvhNR>rPJFW*)W69(vErNP3&vKbgAY;WGYQ2_G)kzxP{FavQrH#c|bw{PE^|NsBL sk5mIdK!%Hp>ynI&Ozy2)x0Zqg0JuRO8yiKn@Bjb+07*qoM6N<$g1u>al>h($ literal 0 HcmV?d00001 diff --git a/src/duckstation-qt/resources/icons/actions-tools-wizard@2x.png b/src/duckstation-qt/resources/icons/actions-tools-wizard@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..34e4a79ba16d31663ee7ec4b3bab34e99ed40229 GIT binary patch literal 2122 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 AdjJ3c literal 0 HcmV?d00001 diff --git a/src/duckstation-qt/resources/resources.qrc b/src/duckstation-qt/resources/resources.qrc index ba533b5cd..c1e775c78 100644 --- a/src/duckstation-qt/resources/resources.qrc +++ b/src/duckstation-qt/resources/resources.qrc @@ -19,6 +19,10 @@ icons/star-4.png icons/star-5.png icons/address-book-new-22.png + icons/actions-tools-wizard.png + icons/actions-tools-wizard@2x.png + icons/actions-tools-wizard-32.png + icons/actions-tools-wizard-32@2x.png icons/applications-internet.png icons/system-search.png icons/list-add.png