From ce93c8522e4233cb827f84a9b583142fe510db16 Mon Sep 17 00:00:00 2001 From: Nix <75538775+nixietab@users.noreply.github.com> Date: Tue, 23 Apr 2024 06:43:26 -0300 Subject: [PATCH] added the marroc mod manager --- marroc.ico | Bin 0 -> 7324 bytes marroc.py | 366 +++++++++++++++++++++++++++++++++++++++++++++++++++ picodulce.py | 19 ++- 3 files changed, 384 insertions(+), 1 deletion(-) create mode 100644 marroc.ico create mode 100644 marroc.py diff --git a/marroc.ico b/marroc.ico new file mode 100644 index 0000000000000000000000000000000000000000..f559b1c698c4c74d950cb779f6e2594da47f4c9a GIT binary patch literal 7324 zcma)B1yoeu_C7NXIDkl}A|ah3AdLf(1JVe{5CSS8-6bQXf^>)=A)SK~(lF8rQVOVa zNq0;A2mQZXzxCd`GqdhJ=gzwKd^^6q_t^kIaG$dS0+>L^WdNvg*UvT8m52%H32~Ri zD$4TOXLrwjaD3be<(&86Y~B|GaST&}=8GB6WOo(PKKevj;F(9j6;6zy{**?N(qwB=VIvmQ9?&{H?slUpm@ zbGZFl{8I_-*==Pw ztH34%Drkh~SUp8}cq&e|yW|3u@v9GzcM?GFd}#E|MZHR*fCE8Wymi4==2ouOkEndk zA&o5I=_5YXDc4SOy7$>rU$tJQTXM?s#lOlYY3V-X-liZQZ%vK8wR?FoNVW?J@kKeQ zFH)lj&-_~tXQepzA9B6Qc3O8|v3VMbSH`(Fe6smnE$231? zmr5N)@YVBcJ`CG99!d1hlpr1Vy-ko_Z{uwMh~ER4mx2=;GK|cG43T19Ib~14ef;a2 znbhvj3O;s~x5#&1_g=`U0I8pqf*P3qhQ=h%m@aaUt zJvi9V!n?-Ghh9N~*LCDQOTL{at=WP+_lRUo0}m#r5ttb*aO)4?f5!K3pebESL#K3f z-nhl=E8cZJorFvf%KKRuu(i}^ex;w4WL_(AaH$}i|J0**6@kz3fg^z^B<|= z-x|M5nl~_tmDSD?4s7U6ej78yb+EP&_62h#wju7hN$mUF3_J?#vtKfui__-3`69)e zQ{IitiWTFuI^^>)VjRmZJl1Kp%2JU86Wpyqe#4@#c#t4AOvEB4b|ak$gEt&O>XMbr(%`0xF46$Za(#~-hoMWZ&%XA z$Y_DUEQRb1<_FAekhQfpK(Jt2fr~eYerW&^d?i83Llr|&%7>1d;%gly5AyvbIjp@w zvRg3oeUzj58~V{EBPu#eL!f`*SC*oY(RHCD&f=MeRhv$M`F$aYq&7vV-m%odv0u66 zORsM{A;(H;&lRVf%h#qvl*|+euz{L-q59qjzRLIug{KfUbTYL(a`lsma)M~0c_c-? zDm5=biNP|T0%RMdZOX@umXoTirNZ8z2IMY^c)hE35VarGXW{_AMRRsV3jT=f>c#~@VZ_qKECfP2o`*X7ncvHFN~O3%zVJyJp1yDBAa8YB zw+CJ#OKbI_ItG!<2T@r(YV$I!8Je($bbqV%uFe9U8_irF4M)sc8yZJ!pZq@@Z93V(}y&GPw9eSULzb)R>C)WZk-2mg!6aMYK+wme6)7Ejd>X z1oJ{CmGH=EuoZj{RM?V-G430a~hmAi?MldU$yi>8J=xLznSI1fN&M!DB!haA>cdKj+E z>8v;v5GYdBz}?<(j`mUQZOgI3&8S^TBCK?0hq#slqCO?3Biq!1C{c@@B@7Na*E{I! zuNSmY&|vvgXJW$ItGTFX>f;FtdODVfm_U>UX4Cr4xp_i2t{`|v`B5;fE{h(lfs2H&d}Wo-kTBOf7cuY5TO1blowXTndgP`Y#eWvsN@X z6Okn)qLknGJkvl`+!APzlG+MaRW$^eO)XoRIN$Xo<%iY0yQ-dsvg*fY#w0(~E+M1H z6rj$mO<*g6Jq0Hc8$-08%hPYjZQ0H!57?HMYi05?|4I_sAiNF72F3?JRqPK}Wh)@e zolsyMHWudR(}P@CN~)04EjX6yIdG1DJGAwKkZW^&lo>>Rvb3#T4plHIZ&{*dLO1dO zOc)74Nx4xDY+@%^??1A~zbG4z9GpJ>e7w6~>6AbIy*(^F$ILd_mjRoC1nOI!jpjbw zizqt%iLoayABUhOWu9GqIS7I4t@7D&UxcW!mB2PVK z>?t=$mW>4^QR_!aIijRe=(>Iftyie?{hx#EffuPiWMZo*k(`I;WAA+FcmBY0Ic+8r zujbcQ1KZMa^#c3QcU24?XGl9^vq=fl!TeQzpt9fjp6WSZoxC$W;$*OB<}yWj7sT+a z;8c!ugy^a{wzB*ez5fX{XC#bBfaYYHn#rnk?;#cRd1dY1d9joyZ*lg$j-x_!IP`j4@k5_1<#H^n45fC`U6~tJ zYRi|P%`QOm%Z1Y~2^l*RCG1C->qn{>k<;6$5WZ=fqBx3`TQ@-QcM(}}KcpSwSTou@ z^gLd4*x`F&MY&7VolUI-Bizq0@3~&r`*T;_5Hd1g=lv^a22U7u%kc6t zom*;bAGx9kts{0=(p~*@IOFHz_n3M>u?1PO1f?e~=X)d6?(yY2$8M<8$^K_-Je%PrT9E;2!Wsbf0t=_NLHVEx$RBrOiy(X5tG*6yj=U?D?al3mvu zt^nKLw;nOlplpon3DT3tye4ITjgl}@Pmll3T>n!5{l`7D8kE*RLfNIn+PzP>@0D{! ziedJ1QFIV^@P3k=vDx`$`v?I>a6#i8Xdr}mhKJqsNlo>clJ!37mGPc>a^dorMkM1m zmG-@ngy{CQ>XZht8pUnBfh`-B@*jy_WR!ux(_cz-E69|jyFDs0`^$!VvtaAqMgP>t zKEIgZ*s!`18OFU!u2c0xjSBvr2hXPF%j^7i$-I9~q?qejqKrGjltYN(P_0ZLH5o0f zuU*`BK)d;_%eAO%a_UuP#zzuJmzY3*?OduhMcVf%-?xp`{$sZKVY#-s;ABeu z8u|VwVfyD;lG`tkS_p_*Jv$1TN|Aag^=kgXPmA{U-X-Y%j!>G`^V;v;H_b38Pje#a zo#1%N7)nGhO*Vt*xLV|x2Z^+^qel1T(Z=LdpCeffqKQ!RtAa$%P_~IjD_45w%J+C${ z9WH!nHpZBmNwlx5P!9FJd}+;s+Ir4@SF$|mWWA)v=MLyvGxato-@7yvwO8(zU#KHr z)F0kytb|KPPF%(+QH}M_L`0>OVqCi0dpkd#j^{Gwh;$wH#nnEAi99Fb&0Z~+Cq1!+{y8o$;nfT z?aZ~yG?VdbS8^*&{kwx+oWPsVncS-@KqEp z!3>+;o}FYJ6^)aW>b{NSjOn>PY4(D>VdvQ#9ut9pvv|Yajl%moYBwb}aiPh?)aoiX z*fG{%7|re$x#h}F!F^AM+es2O;dD1t0YFqBK}cQTL&%Ai{@;?5sI@eR-^-&5R`rK# za{>=$rmAxn_T29&DTc}el*+?;jh-iu3S?3y{HOx~is9kQbq~KWa>NB_haM0u+^`AI z3QiRo2o2$m#rXrz_MmM~zr*9rV{5N1j#K5vR55j$)cQ1jDGw{}RB3sKlZm&ug5$Qp zC0p{Zy2)M2x7?ca(!|C>D&6QK_Y5x(i~gnw&m!Z^H4et~HJP`8Hn;GDk87?jK#Qyt zMjhWNL#`7}mTT4RIC{IEW069v+7;|-r>i5Z(diZ% zU!!P;%sQ(o<`K!7n>6ttapRtNRh^h2O$D`{Zk+h!h(R<>?jw5o%_9rIF;Tml5woyA z9U0LdnO667v2dD>CTu_rig}1F6C9y;)y2 z@xMgh-*H0fRU&{8fxisLs=lwg({}UN?iVM&jPDXo`-{v9_pxtlu+A&k*u3)DMls_ff2TVVp<_G1bgs?PCN1~fdA zL^mGLdD(kLu+F`XeDg(BeWYo+NDHb=#aYe#_ek)c>rgble83Ex2Oqc8pp0R9i$9&c^*lsRtEXtZbk4V~UsN*CUeWd*|%CULCI0J!$aw z%(bw^_`=b99}j=_Fl`uns(bzo&?QKb2#fH@BTGwpA**yj_S7R>g-I{0aE%Zk*J#5iMFm{Ds&CN7r{OwPZC<a@xA%Q z$}pyn_!T`lnyeP&4{FU8as~lkY6{(6@_wFx(P+-}6a$&6NXi!q9~hc@nY*R%71$B~SUwT~snd}eL8 zr#ae7Jw+!HcRa3#f5fG9TMwi5`K36*y~xqYgg5y&tpyMRCaEyTPu+%nlIU}xLZM%( zGcNA7G$~FWt)w``SU$q0z}($it%jT6qs!Rvt*aRvEHu?!h0hJb+1RWIZOW_t#idUx zj9nM!x9iqBUe148H8LLfzI8?zDQXsH^m{~?)j-noS@9mENR;Ky@niO?x*@w@#>S5x zCimsyBpRJe2+ZVIDwi)yGx?pzqVlVd0flpmFN1x()68SW-|)+dr5lkux^Q44ubkJn z45_Rwlw^M_^20I=0liXEDJ~cPfi^f$5#RhyiFBnt>DZ0sYwS41)f=uK&P-zpOFp=| z4Y>Qv&IJ)~{-PCUr}Cqkjqc3a?Cc&8?}tX^C<$`84L6fJ@_@<`{>H-L*Bf(vMfP?B z#kLx;?0$#yzh0%_Lehs$mlg)^VLY1Uw*Xq|B5pk=XR_H93xRY<4^yLn6C8mAY!v^M zS>i%~H=9O>D&932Ry6%X8rU@+Sns4ABr1i7jpP6KJ2@eBWqeepW)A)V?t8P{sVA&{ z7@?nD5XYfm?#5N+Z)+z(7iwuEqnE2B^;la=2F6G!0gnBA1 z)>XJL>4ie~tD63KCpI&q!ep-;#*SJVW!`?KCY*N8=(^gA!@k& z*%XS!tXI0w#2^rA0tVl0cOrJh@gbg?U_^({dPr|?CRD<@hW=LcyTlrzr~slcOxTSc zPv==xFrwmN=!bg2R*~b@`jfv}TlX+rP$q$VF38WGZN-K7xo9#Ek)Jg_tLgA%&5t5D zUa)O|VTnaY>$Hc78D8?1lRehkMX2ly-+G3;uk77A)$xb|J%Ow}I54yp4YE`?TO_Ux zgaEjv5N_pX0MNfz{%5k~lnVQ{9Nbx4tyxiyS%rUnt)P_tKtJtWV;`lTv3n})+64%c zOaWM=tflf$CEZ@I2(!8Bkh3VVNSaYAoBQU$)vL{+srb!q8i+CXZ}-$5Xt}*$k&Sg_ zE>AzmA;%_u^&M`R-Ea>uN^=mA2-sS4n)$0q#&yP?yKZnFahGrS(`0 literal 0 HcmV?d00001 diff --git a/marroc.py b/marroc.py new file mode 100644 index 0000000..de5e6ee --- /dev/null +++ b/marroc.py @@ -0,0 +1,366 @@ +import sys +import os +import shutil +import json +import requests +from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QListWidget, QListWidgetItem, QMessageBox, QComboBox, QDialog, QTabWidget, QFileDialog, QListView +from PyQt5.QtCore import Qt, QSize, QDir, QStringListModel +from PyQt5.QtGui import QPixmap, QIcon, QPalette, QColor + + + +CONFIG_FILE = "config.json" + +class ModrinthSearchApp(QWidget): + def __init__(self): + super().__init__() + + self.setWindowTitle("Marroc Mod Manager") + self.setGeometry(100, 100, 500, 400) + + palette = QPalette() + palette.setColor(QPalette.Window, QColor(53, 53, 53)) + palette.setColor(QPalette.WindowText, Qt.white) + palette.setColor(QPalette.Base, QColor(25, 25, 25)) + palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) + palette.setColor(QPalette.ToolTipBase, Qt.white) + palette.setColor(QPalette.ToolTipText, Qt.white) + palette.setColor(QPalette.Text, Qt.white) + palette.setColor(QPalette.Button, QColor(53, 53, 53)) + palette.setColor(QPalette.ButtonText, Qt.white) + palette.setColor(QPalette.BrightText, Qt.red) + palette.setColor(QPalette.Link, QColor(42, 130, 218)) + palette.setColor(QPalette.Highlight, QColor(42, 130, 218)) + palette.setColor(QPalette.HighlightedText, Qt.white) + self.setPalette(palette) + + + layout = QVBoxLayout() + + tab_widget = QTabWidget() + self.search_tab = QWidget() + self.mods_tab = QWidget() + + tab_widget.addTab(self.search_tab, "Search") + tab_widget.addTab(self.mods_tab, "Mods") + + self.init_search_tab() + self.init_mods_tab() + + layout.addWidget(tab_widget) + + self.setLayout(layout) + + def init_search_tab(self): + layout = QVBoxLayout() + + self.search_input = QLineEdit() + self.search_input.setPlaceholderText("Enter mod name...") + layout.addWidget(self.search_input) + + self.search_button = QPushButton("Search") + self.search_button.clicked.connect(self.search_mods) + layout.addWidget(self.search_button) + + self.mods_list = QListWidget() + layout.addWidget(self.mods_list) + + self.select_button = QPushButton("Select Mod") + self.select_button.clicked.connect(self.show_mod_details_window) + layout.addWidget(self.select_button) + + self.selected_mod = None + + self.search_tab.setLayout(layout) + + def init_mods_tab(self): + layout = QVBoxLayout() + self.mod_manager = ModManager() # Integrate ModManager into Mods Tab + layout.addWidget(self.mod_manager) + self.mods_tab.setLayout(layout) + + def search_mods(self): + self.mods_list.clear() + mod_name = self.search_input.text() + api_url = f"https://api.modrinth.com/v2/search?query={mod_name}&limit=20&facets=%5B%5B%22project_type%3Amod%22%5D%5D" + response = requests.get(api_url) + if response.status_code == 200: + mods_data = json.loads(response.text) + for mod in mods_data['hits']: + mod_name = mod['title'] + mod_description = mod['description'] + item = QListWidgetItem(f"Title: {mod_name}\nDescription: {mod_description}") + item.setSizeHint(QSize(100, 50)) # Set size hint to increase height + item.mod_data = mod + self.mods_list.addItem(item) + else: + self.mods_list.addItem("Failed to fetch mods. Please try again later.") + + def show_mod_details_window(self): + selected_item = self.mods_list.currentItem() + if selected_item is not None: + mod_data = selected_item.mod_data + mod_slug = mod_data.get('slug') + if mod_slug: + api_url = f"https://api.modrinth.com/v2/project/{mod_slug}" + response = requests.get(api_url) + if response.status_code == 200: + mod_info = json.loads(response.text) + icon_url = mod_info.get('icon_url') + mod_versions = self.get_mod_versions(mod_slug) + mod_details_window = ModDetailsWindow(mod_data, icon_url, mod_versions) + mod_details_window.exec_() + else: + QMessageBox.warning(self, "Failed to Fetch Mod Details", "Failed to fetch mod details. Please try again later.") + else: + QMessageBox.warning(self, "No Mod Slug", "Selected mod has no slug.") + else: + QMessageBox.warning(self, "No Mod Selected", "Please select a mod first.") + + def get_mod_versions(self, mod_slug): + api_url = f"https://api.modrinth.com/v2/project/{mod_slug}/version" + response = requests.get(api_url) + if response.status_code == 200: + versions = json.loads(response.text) + mod_versions = [] + for version in versions: + version_name = version['name'] + version_files = version.get('files', []) + if version_files: + file_urls = [file['url'] for file in version_files] + mod_versions.append({'version': version_name, 'files': file_urls}) + else: + mod_versions.append({'version': version_name, 'files': []}) + return mod_versions + else: + return [] + +class ModManager(QWidget): + def __init__(self): + super().__init__() + self.setWindowTitle("Mod Manager") + self.setGeometry(100, 100, 600, 400) + + self.load_config() + self.mods = [] + self.available_mods = [] + + layout = QHBoxLayout() + + layout_mods = QVBoxLayout() + layout_buttons = QVBoxLayout() + layout_arrow = QVBoxLayout() + layout_available_mods = QVBoxLayout() + + self.list_view_mods = QListView() + self.list_view_mods.doubleClicked.connect(self.move_mod_to_local) + self.list_view_available_mods = QListView() + self.list_view_available_mods.doubleClicked.connect(self.move_mod_to_minecraft) + self.populate_mod_list() + + self.arrow_right_button = QPushButton(">") + self.arrow_right_button.setIcon(QIcon('arrow_right.png')) + self.arrow_right_button.setIconSize(QSize(32, 32)) + self.arrow_right_button.clicked.connect(self.move_mod_to_minecraft) + + self.arrow_left_button = QPushButton("<") + self.arrow_left_button.setIcon(QIcon('arrow_left.png')) + self.arrow_left_button.setIconSize(QSize(32, 32)) + self.arrow_left_button.clicked.connect(self.move_mod_to_local) + + self.delete_button = QPushButton("Delete") + self.delete_button.clicked.connect(self.delete_mod) + + self.config_button = QPushButton("Config") + self.config_button.clicked.connect(self.select_mods_directory) + + self.refresh_button = QPushButton("Refresh") + self.refresh_button.clicked.connect(self.refresh_mod_list) + + layout_mods.addWidget(self.list_view_mods) + layout_buttons.addWidget(self.arrow_right_button) + layout_buttons.addWidget(self.arrow_left_button) + layout_buttons.addWidget(self.delete_button) + layout_buttons.addWidget(self.config_button) + layout_buttons.addWidget(self.refresh_button) # Add refresh button + layout_arrow.addLayout(layout_buttons) + layout_available_mods.addWidget(self.list_view_available_mods) + + layout.addLayout(layout_mods) + layout.addLayout(layout_arrow) + layout.addLayout(layout_available_mods) + + self.setLayout(layout) + + # Other methods remain unchanged + + def refresh_mod_list(self): + self.populate_mod_list() + + def load_config(self): + if os.path.exists(CONFIG_FILE): + with open(CONFIG_FILE, 'r') as f: + config = json.load(f) + self.mod_folder = config.get('mod_folder') + if not self.mod_folder: + self.set_default_mod_folder() + else: + self.set_default_mod_folder() + + def set_default_mod_folder(self): + if sys.platform == 'win32': + self.mod_folder = os.path.expandvars('%APPDATA%\\.picomc\\instances\\default\\mods') + elif sys.platform == 'linux': + self.mod_folder = os.path.expanduser('~/.local/share/picomc/instances/default/minecraft/mods') + else: + self.mod_folder = QDir.homePath() + + def save_config(self): + config = {'mod_folder': self.mod_folder} + with open(CONFIG_FILE, 'w') as f: + json.dump(config, f) + + def populate_mod_list(self): + self.available_mods = os.listdir(self.mod_folder) + self.mods = [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.jar')] + + self.model_mods = QStringListModel(self.mods) + self.model_available_mods = QStringListModel(self.available_mods) + + self.list_view_mods.setModel(self.model_mods) + self.list_view_available_mods.setModel(self.model_available_mods) + + def move_mod_to_minecraft(self): + selected_mod_index = self.list_view_mods.currentIndex() + selected_mod = self.mods[selected_mod_index.row()] + destination_path = os.path.join(self.mod_folder, os.path.basename(selected_mod)) + + if os.path.exists(destination_path): + QMessageBox.warning(self, "Error", "A mod with the same name already exists in the mods folder.") + else: + shutil.move(selected_mod, self.mod_folder) + self.available_mods.append(selected_mod) + self.model_available_mods.setStringList(self.available_mods) + + # Update the lists + self.populate_mod_list() + self.save_config() + + def move_mod_to_local(self): + selected_mod_index = self.list_view_available_mods.currentIndex() + selected_mod = self.available_mods[selected_mod_index.row()] + destination_path = os.path.join(os.getcwd(), os.path.basename(selected_mod)) + + if os.path.exists(destination_path): + QMessageBox.warning(self, "Error", "A mod with the same name already exists in the current directory.") + else: + shutil.move(os.path.join(self.mod_folder, selected_mod), os.getcwd()) + self.mods.append(selected_mod) + self.model_mods.setStringList(self.mods) + + # Update the lists + self.populate_mod_list() + self.save_config() + + def delete_mod(self): + selected_mod_index = self.list_view_available_mods.currentIndex() + selected_mod = self.available_mods[selected_mod_index.row()] + + reply = QMessageBox.question(self, 'Confirmation', f"Are you sure you want to delete '{selected_mod}'?", + QMessageBox.Yes | QMessageBox.No, QMessageBox.No) + if reply == QMessageBox.Yes: + os.remove(os.path.join(self.mod_folder, selected_mod)) + self.available_mods.remove(selected_mod) + self.model_available_mods.setStringList(self.available_mods) + self.save_config() + + def select_mods_directory(self): + directory = QFileDialog.getExistingDirectory(self, "Select Minecraft Mods Directory", self.mod_folder) + if directory: + self.mod_folder = directory + self.populate_mod_list() + self.save_config() + + +class ModDetailsWindow(QDialog): + def __init__(self, mod_data, icon_url, mod_versions): + super().__init__() + + self.setWindowTitle("Mod Details") + self.setGeometry(100, 100, 400, 300) + + self.mod_data = mod_data # Store mod data + + layout = QVBoxLayout() + + mod_name_label = QLabel(f"

{mod_data['title']}

") + mod_name_label.setAlignment(Qt.AlignCenter) + layout.addWidget(mod_name_label) + + mod_description_label = QLabel(mod_data['description']) + mod_description_label.setWordWrap(True) + layout.addWidget(mod_description_label) + + icon_pixmap = self.load_icon(icon_url) + icon_label = QLabel() + if icon_pixmap: + icon_label.setPixmap(icon_pixmap.scaledToWidth(200)) + icon_label.setAlignment(Qt.AlignCenter) + layout.addWidget(icon_label) + + self.version_dropdown = QComboBox() + for version in mod_versions: + self.version_dropdown.addItem(version['version']) + self.version_dropdown.setItemData(self.version_dropdown.count() - 1, version['files'], Qt.UserRole) + layout.addWidget(self.version_dropdown) + + self.download_button = QPushButton("Download") + self.download_button.clicked.connect(self.download_mod) + layout.addWidget(self.download_button) + + self.download_url_label = QLabel() + self.download_url_label.setAlignment(Qt.AlignCenter) + layout.addWidget(self.download_url_label) + + layout.addStretch(1) + + self.setLayout(layout) + + def load_icon(self, icon_url): + try: + response = requests.get(icon_url) + if response.status_code == 200: + pixmap = QPixmap() + pixmap.loadFromData(response.content) + return pixmap + else: + return None + except Exception as e: + print("Error loading icon:", e) + return None + + def download_mod(self): + selected_version_index = self.version_dropdown.currentIndex() + selected_version_files = self.version_dropdown.itemData(selected_version_index, Qt.UserRole) + if selected_version_files: + for file_url in selected_version_files: + filename = os.path.basename(file_url) + try: + response = requests.get(file_url) + response.raise_for_status() + with open(filename, 'wb') as f: + f.write(response.content) + QMessageBox.information(self, "Download Mod", f"Downloaded {filename} successfully.") + return + except requests.exceptions.RequestException as e: + QMessageBox.warning(self, "Download Error", f"Error downloading mod: {e}") + return + QMessageBox.warning(self, "Download Mod", "Failed to download the mod.") + +if __name__ == "__main__": + app = QApplication(sys.argv) + app_icon = QIcon('marroc.ico') # Provide the path to your icon file + app.setWindowIcon(app_icon) # Set the application icon + window = ModrinthSearchApp() + window.show() + sys.exit(app.exec_()) \ No newline at end of file diff --git a/picodulce.py b/picodulce.py index 98a5bbe..87e7b4a 100644 --- a/picodulce.py +++ b/picodulce.py @@ -2,6 +2,7 @@ import sys import subprocess import threading import logging +import os from PyQt5.QtWidgets import QApplication, QComboBox, QWidget, QVBoxLayout, QPushButton, QMessageBox, QDialog, QHBoxLayout, QLabel, QLineEdit, QCheckBox from PyQt5.QtGui import QFont, QIcon, QColor, QPalette from PyQt5.QtCore import Qt @@ -64,6 +65,12 @@ class PicomcVersionSelector(QWidget): self.install_mod_loader_button.clicked.connect(self.open_mod_loader_menu) buttons_layout.addWidget(self.install_mod_loader_button) + # Create a button for the marroc mod loader + self.open_marroc_button = QPushButton('Marroc Mod Manager') + self.open_marroc_button.clicked.connect(self.open_marroc_script) + buttons_layout.addWidget(self.open_marroc_button) + + # Create About button self.about_button = QPushButton('About') self.about_button.clicked.connect(self.show_about_dialog) @@ -106,6 +113,16 @@ class PicomcVersionSelector(QWidget): self.installed_version_combo.clear() self.installed_version_combo.addItems(versions) + def open_marroc_script(self): + try: + # Replace 'path_to_marroc.py' with the actual path to marroc.py + subprocess.Popen(['python', 'marroc.py']) + except FileNotFoundError: + logging.error("'marroc.py' not found.") + QMessageBox.critical(self, "Error", "'marroc.py' not found.") + + + def play_instance(self): if self.installed_version_combo.count() == 0: QMessageBox.warning(self, "No Version Available", "Please download a version first.") @@ -436,4 +453,4 @@ if __name__ == '__main__': app = QApplication(sys.argv) window = PicomcVersionSelector() window.show() - sys.exit(app.exec_()) + sys.exit(app.exec_()) \ No newline at end of file