Compare commits
8 Commits
RA3附属mod下载
...
master
Author | SHA1 | Date | |
---|---|---|---|
b7b3e2d55d | |||
2e2617627d | |||
e3140f656f | |||
f9a09d1d87 | |||
23ea5d0dc6 | |||
2c0b265698 | |||
e04718f830 | |||
185efc1f96 |
166
.gitignore
vendored
Normal file
166
.gitignore
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# others
|
||||
log/
|
||||
.7z
|
||||
注册表.txt
|
||||
.pyc
|
3
RA3_affiliated_mod_downloader.json
Normal file
3
RA3_affiliated_mod_downloader.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version":"1.1.0"
|
||||
}
|
@ -5,8 +5,9 @@
|
||||
@Contact : Hatanezumi@chunshengserver.cn
|
||||
'''
|
||||
import os
|
||||
import json
|
||||
import winreg
|
||||
import requests
|
||||
import ctypes.wintypes
|
||||
|
||||
def get_mods(base_path:str) -> tuple[bool,str|list[str]]:
|
||||
if os.path.exists(base_path) is False:
|
||||
@ -43,7 +44,45 @@ def get_cloud(path:str, target, arg):
|
||||
if req.status_code != 200:
|
||||
target(arg,False,"返回值为:{}".format(req.status_code))
|
||||
return
|
||||
res = json.loads(req.content)
|
||||
res = req.content
|
||||
target(arg,True,res)
|
||||
except Exception as err:
|
||||
target(arg,False,err)
|
||||
target(arg,False,err)
|
||||
def get_ra3_path(base_reg_path:str = None) -> tuple[bool,str]:
|
||||
try:
|
||||
if base_reg_path is None:
|
||||
base_reg_path = 'SOFTWARE\\WOW6432Node'
|
||||
key = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE,base_reg_path + '\\Electronic Arts\\Electronic Arts\\Red Alert 3')
|
||||
dir = winreg.QueryValueEx(key,'Install Dir')
|
||||
return (True,dir[0])
|
||||
except FileNotFoundError:
|
||||
if base_reg_path == 'SOFTWARE\\WOW6432Node':
|
||||
return get_ra3_path('SOFTWARE\\')
|
||||
else:
|
||||
return (False,'未找到RA3根目录,你确定安装了吗?或尝试修复注册表')
|
||||
except Exception as err:
|
||||
return (False,err)
|
||||
def get_mod_path() -> tuple[str,str]:
|
||||
'''
|
||||
返回文档路径和mod路径
|
||||
'''
|
||||
try:
|
||||
buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
|
||||
ctypes.windll.shell32.SHGetFolderPathW(None, 5, None, 0, buf)
|
||||
if buf == '':
|
||||
raise Exception('目录获取失败')
|
||||
documents_path = buf.value
|
||||
except:
|
||||
documents_path = os.path.join(os.path.splitdrive(os.environ['systemroot'])[0],os.environ['homepath'],'Documents')
|
||||
base_mod_path = os.path.join(documents_path,'Red Alert 3','Mods')
|
||||
return (documents_path,base_mod_path)
|
||||
def get_ARModLauncher_path() -> tuple[bool,str]:
|
||||
try:
|
||||
key = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\ARModLauncher.exe')
|
||||
dir = winreg.QueryValueEx(key,'')
|
||||
dir = os.path.split(dir[0])[0]
|
||||
return (True,dir)
|
||||
except FileNotFoundError:
|
||||
return (False,'未找到AR启动器目录')
|
||||
except Exception as err:
|
||||
return (False,err)
|
Binary file not shown.
Binary file not shown.
188
src/main.py
188
src/main.py
@ -6,6 +6,7 @@
|
||||
'''
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import py7zr
|
||||
import requests
|
||||
import webbrowser
|
||||
@ -22,6 +23,7 @@ REFRESH = 101
|
||||
GETMODS = 200
|
||||
GETMODINFO = 201
|
||||
GETNEWVERSION = 202
|
||||
GETUPDATELOG = 203
|
||||
GETOTHER = 210
|
||||
INFO = 300
|
||||
WARNING = 301
|
||||
@ -33,10 +35,11 @@ class CustomizeSingals(QObject):
|
||||
set_listView_Network = Signal(dict)
|
||||
set_Status_Tip = Signal(str)
|
||||
set_progressBar_Download = Signal(int)
|
||||
download_finished = Signal(str)
|
||||
download_finished = Signal(str,dict)
|
||||
download_err = Signal(Exception)
|
||||
set_new_version = Signal(str)
|
||||
get_new_version_err = Signal(str)
|
||||
set_plainTextEdit_updatelog = Signal(str)
|
||||
class Process():
|
||||
@staticmethod
|
||||
def set_comboBox(comboBox:QComboBox, texts:list):
|
||||
@ -56,12 +59,15 @@ class Process():
|
||||
singals.set_Status_Tip.connect(window.set_Status_Tip)
|
||||
singals.set_new_version.connect(window.set_new_version)
|
||||
singals.get_new_version_err.connect(window.get_new_version_err)
|
||||
singals.set_plainTextEdit_updatelog.connect(window.set_plainTextEdit_updatelog)
|
||||
if not state:
|
||||
if mode == INIT:
|
||||
if source == GETMODS:
|
||||
singals.set_Status_Tip.emit('获取云AR信息失败:{}'.format(res))
|
||||
elif source == GETNEWVERSION:
|
||||
singals.get_new_version_err.emit(res)
|
||||
elif source == GETUPDATELOG:
|
||||
singals.set_plainTextEdit_updatelog.emit('获取更新日志失败:{}'.format(res))
|
||||
return
|
||||
elif mode == REFRESH:
|
||||
if source == GETMODS:
|
||||
@ -69,15 +75,17 @@ class Process():
|
||||
elif source == GETMODINFO:
|
||||
singals.message_box.emit(WARNING,'出现错误',"获取mod信息失败:{}".format(res),QMessageBox.Ok,QMessageBox.Ok)
|
||||
if source == GETMODS:
|
||||
singals.set_listView_Network.emit(res)
|
||||
singals.set_listView_Network.emit(json.loads(res))
|
||||
elif source == GETMODINFO:
|
||||
singals.set_network_page.emit(res)
|
||||
singals.set_network_page.emit(json.loads(res))
|
||||
elif source == GETNEWVERSION:
|
||||
singals.set_new_version.emit(res['version'])
|
||||
singals.set_new_version.emit(json.loads(res)['version'])
|
||||
elif source == GETUPDATELOG:
|
||||
singals.set_plainTextEdit_updatelog.emit(res.decode())
|
||||
except Exception as err:
|
||||
singals.message_box.emit((WARNING,'出现错误',"获取信息失败:{}".format(err),QMessageBox.Ok,QMessageBox.Ok))
|
||||
@staticmethod
|
||||
def download(window:QMainWindow,url:str,path:str):
|
||||
def download(window:QMainWindow,url:str,path:str,info:dict):
|
||||
signals = CustomizeSingals()
|
||||
signals.set_progressBar_Download.connect(window.set_progressBar_Download)
|
||||
signals.download_finished.connect(window.download_finished)
|
||||
@ -85,20 +93,35 @@ class Process():
|
||||
if not os.path.exists(os.path.split(path)[0]):
|
||||
signals.download_err.emit('目录不存在:{}'.format(os.path.split(path)[0]))
|
||||
return
|
||||
res = requests.get(url, stream=True,headers={"Accept-Encoding":"identity"})
|
||||
size = 0#初始化已下载大小
|
||||
chunk_size = 1024#单次下载量
|
||||
content_size = int(res.headers['content-length'])#总大小
|
||||
try:
|
||||
res = requests.get(url, stream=True,headers={"Accept-Encoding":"identity"},timeout=10)
|
||||
size = 0#初始化已下载大小
|
||||
chunk_size = 1024#单次下载量
|
||||
content_size = int(res.headers['content-length'])#总大小
|
||||
if res.status_code == 200:
|
||||
with open(path,'wb') as file:
|
||||
for data in res.iter_content(chunk_size=chunk_size):
|
||||
if window.isdownloading is False:
|
||||
file.close()
|
||||
os.remove(path)
|
||||
signals.set_progressBar_Download.emit(0)
|
||||
return
|
||||
file.write(data)
|
||||
size += len(data)
|
||||
signals.set_progressBar_Download.emit(int(size / content_size * 100))
|
||||
signals.download_finished.emit(path)
|
||||
signals.download_finished.emit(path,info)
|
||||
except Exception as err:
|
||||
signals.download_err.emit(err)
|
||||
@staticmethod
|
||||
def clear_localPage_everything(window:QMainWindow):
|
||||
'''
|
||||
清除本地页面中能显示的所有的物体的内容
|
||||
'''
|
||||
window.comboBox_mods.clear()
|
||||
window.listView_local_qsl.setStringList([])
|
||||
window.listView_loaded_qsl.setStringList([])
|
||||
window.lineEdit_nowpath.setText('')
|
||||
window.label_nowdir.setText('')
|
||||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
def __init__(self, parent=None) -> None:
|
||||
#基础设置
|
||||
@ -107,7 +130,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
if os.path.exists(os.path.join(os.getcwd(),'ui','ra3.ico')):
|
||||
self.icon = QIcon(os.path.join(os.getcwd(),'ui','ra3.ico'))
|
||||
self.setWindowIcon(self.icon)
|
||||
self.version = '1.0.0'
|
||||
self.version = '1.1.0'
|
||||
#--------------------------
|
||||
#连接信号
|
||||
self.comboBox_mods.currentIndexChanged.connect(self.__comboBox_mods_changed)#下拉框内容改变
|
||||
@ -123,6 +146,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
self.pushButton_refresh.clicked.connect(self.__on_pushButton_refresh_clicked)#刷新按钮被按下
|
||||
self.pushButton_Download.clicked.connect(self.__on_pushButton_Download_clicked)#下载按钮被按下
|
||||
self.pushButton_release.clicked.connect(self.__on_pushButton_release_clicked)#发布页按钮被按下
|
||||
self.pushButton_changeDir_RA3.clicked.connect(self.__on_pushButton_changeDir_RA3_clicked)#切换到RA3目录按钮被按下
|
||||
self.pushButton_changeDir_mod.clicked.connect(self.__on_pushButton_changeDir_mod_clicked)#切换到mod目录被按下
|
||||
self.pushButton_localRefresh.clicked.connect(self.__on_pushButton_localRefresh_clicked)#本地刷新按钮被按下
|
||||
self.pushButton_changeDir_ARModLauncher.clicked.connect(self.__on_pushButton_changeDir_ARModLauncher_clicked)#切换到AR启动器目录按钮被按下
|
||||
#--------------------------
|
||||
#变量注册(全局变量)
|
||||
self.select_mod = ''
|
||||
@ -130,10 +157,25 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
self.listView_local_qsl = QStringListModel()
|
||||
self.listView_Network_qsl = QStringListModel()
|
||||
self.fileDialog = QFileDialog(self)
|
||||
self.base_mod_path = os.path.join(os.path.splitdrive(os.environ['systemroot'])[0],os.environ['homepath'],'Documents','Red Alert 3','Mods')
|
||||
self.documents_path, self.base_mod_path = AutoProcess.get_mod_path()
|
||||
self.cloud_mods = {}
|
||||
self.cloud_mod_source = (None,{})
|
||||
self.isdownloading = False
|
||||
self.selected_mod_info = {}
|
||||
self.download_info = (None,None)#第一个参数为线程,第二个参数为保存地址
|
||||
self.ra3_path = AutoProcess.get_ra3_path()
|
||||
if self.ra3_path[0] is False:
|
||||
self.ra3_path = ''
|
||||
self.pushButton_changeDir_RA3.setEnabled(False)
|
||||
QMessageBox.warning(self,'获取RA3目录失败','无法获取RA3目录,原因:{}'.format(self.ra3_path[1]),QMessageBox.StandardButton.Ok,QMessageBox.StandardButton.Ok)
|
||||
else:
|
||||
self.ra3_path = self.ra3_path[1]
|
||||
self.ARModLauncher_path = AutoProcess.get_ARModLauncher_path()
|
||||
if self.ARModLauncher_path[0] is False:
|
||||
self.ARModLauncher_path = ''
|
||||
self.pushButton_changeDir_ARModLauncher.setEnabled(False)
|
||||
else:
|
||||
self.ARModLauncher_path = os.path.join(self.ARModLauncher_path[1],'Resources','CustomContent')
|
||||
#--------------------------
|
||||
#初始化内容
|
||||
self.mods = AutoProcess.get_mods(self.base_mod_path)
|
||||
@ -143,7 +185,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
Process.set_comboBox(self.comboBox_mods,[os.path.splitext(os.path.split(mod_name)[1])[0] for mod_name in self.mods[1]])
|
||||
self.label_about_verison.setText('当前版本:{}'.format(self.version))
|
||||
#绑定模型
|
||||
self.listView_loacl.setModel(self.listView_local_qsl)
|
||||
self.listView_local.setModel(self.listView_local_qsl)
|
||||
self.listView_loaded.setModel(self.listView_loaded_qsl)
|
||||
self.listView_Network.setModel(self.listView_Network_qsl)
|
||||
#显示当前目录
|
||||
@ -154,18 +196,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
#获取更新信息
|
||||
t = Thread(target=AutoProcess.get_cloud,args=('https://www.chunshengserver.cn/files/RA3mods/RA3_affiliated_mod_downloader.json',Process.get_cloud_data,(self,INIT,GETNEWVERSION)),daemon=True)
|
||||
t.start()
|
||||
#获取更新日志
|
||||
t = Thread(target=AutoProcess.get_cloud,args=('https://www.chunshengserver.cn/files/RA3mods/更新日志.txt',Process.get_cloud_data,(self,INIT,GETUPDATELOG)),daemon=True)
|
||||
t.start()
|
||||
def __comboBox_mods_changed(self):
|
||||
if self.mods[0] is False:
|
||||
return
|
||||
# currentText = self.comboBox_mods.currentText()#为了保证数据安全采用字符串匹配的方式
|
||||
# find = False
|
||||
# for mod_path in self.mods[1]:
|
||||
# if os.path.split(mod_path)[1].removesuffix('.skudef') == currentText:
|
||||
# self.select_mod = mod_path
|
||||
# find = True
|
||||
# break
|
||||
# if find is False:
|
||||
# return
|
||||
#显示本地列表内容
|
||||
currentIndex = self.comboBox_mods.currentIndex()#因为有重复的名称,所以采用索引匹配
|
||||
mod_path = self.mods[1][currentIndex]
|
||||
@ -185,7 +221,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
#显示保存到文件夹
|
||||
self.lineEdit_savedir.setText(os.path.split(mod_path)[0])
|
||||
def __on_pushButton_R_clicked(self):
|
||||
currentIndex = self.listView_loacl.currentIndex().row()
|
||||
currentIndex = self.listView_local.currentIndex().row()
|
||||
if currentIndex == -1:
|
||||
return
|
||||
select_mod_name = self.listView_local_qsl.stringList()[currentIndex]
|
||||
@ -277,6 +313,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
elif mode == CRITICAL:
|
||||
QMessageBox.Critical(self,title,text,Button,defaultButton)
|
||||
def set_network_page(self,res:dict):
|
||||
self.selected_mod_info = res
|
||||
self.label_name.setText('名称:'+res['name'])
|
||||
self.label_author.setText('作者:'+res['author'])
|
||||
self.label_version.setText('版本:'+res['version'])
|
||||
@ -293,7 +330,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
t.start()
|
||||
def __on_pushButton_Download_clicked(self):
|
||||
if self.isdownloading:
|
||||
QMessageBox.information(self,'无法下载','当前有下载任务在进行',QMessageBox.Ok,QMessageBox.Ok)
|
||||
select = QMessageBox.question(self,'是否终止','确定要终止下载?已下载的进度不会被保存',QMessageBox.Yes|QMessageBox.Cancel,QMessageBox.Cancel)
|
||||
if select == QMessageBox.Yes:
|
||||
self.isdownloading = False
|
||||
self.pushButton_Download.setText('下载')
|
||||
return
|
||||
currentText = self.comboBox_download.currentText()
|
||||
if self.cloud_mod_source[0] != self.listView_Network_qsl.stringList()[self.listView_Network.currentIndex().row()]:
|
||||
@ -307,25 +347,59 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
file_name = link.split('/')[-1]
|
||||
save_path = self.lineEdit_savedir.text()
|
||||
self.isdownloading = True
|
||||
t = Thread(target=Process.download,args=(self,link,os.path.join(save_path,file_name)),daemon=True)
|
||||
self.pushButton_Download.setText('终止')
|
||||
t = Thread(target=Process.download,args=(self,link,os.path.join(save_path,file_name),self.selected_mod_info),daemon=True)
|
||||
self.download_info = (t,os.path.join(save_path,file_name))
|
||||
t.start()
|
||||
def set_progressBar_Download(self,value:int):
|
||||
self.progressBar_Download.setValue(value)
|
||||
def download_finished(self,path:str):
|
||||
def download_finished(self,path:str,info:dict):
|
||||
self.isdownloading = False
|
||||
self.progressBar_Download.value(0)
|
||||
select = QMessageBox.information(self,'下载成功','下载成功,是否自动解压?',QMessageBox.Ok|QMessageBox.Cancel,QMessageBox.Cancel)
|
||||
if select == QMessageBox.Ok:
|
||||
self.progressBar_Download.setValue(0)
|
||||
in_ARModLauncher_path = False
|
||||
self.pushButton_Download.setText('下载')
|
||||
outpath = os.path.split(path)[0]
|
||||
if os.path.split(path)[0] == self.ARModLauncher_path:
|
||||
in_ARModLauncher_path = True
|
||||
outpath = os.path.join(outpath,os.path.split(path)[1].split('.')[0])
|
||||
select = QMessageBox.question(self,'下载成功','下载成功,是否自动解压?',QMessageBox.Yes|QMessageBox.Cancel,QMessageBox.Yes)
|
||||
if select == QMessageBox.Yes:
|
||||
try:
|
||||
if not os.path.exists(outpath):
|
||||
os.mkdir(outpath)
|
||||
with py7zr.SevenZipFile(file=path,mode='r') as file:
|
||||
file.extractall(path=os.path.split(path)[0])
|
||||
file.extractall(path=outpath)
|
||||
except Exception as err:
|
||||
QMessageBox.warning(self,'解压失败','解压失败,原因:{}'.format(err),QMessageBox.Ok,QMessageBox.Ok)
|
||||
return
|
||||
else:
|
||||
QMessageBox.warning(self,'解压成功','解压成功',QMessageBox.Ok,QMessageBox.Ok)
|
||||
QMessageBox.information(self,'解压成功','解压成功',QMessageBox.Ok,QMessageBox.Ok)
|
||||
if in_ARModLauncher_path:
|
||||
select = QMessageBox.question(self,'是否生成配置文件','检测到当前位于AR启动器的目录中,是否生成可以被AR启动器识别的附属mod配置文件?',QMessageBox.Yes|QMessageBox.Cancel,QMessageBox.Yes)
|
||||
if select == QMessageBox.Yes:
|
||||
try:
|
||||
mods = [i for i in os.listdir(outpath) if os.path.splitext(i)[-1].lower() == '.skudef']
|
||||
info_keys = info.keys()
|
||||
mod_info = {}
|
||||
mod_info['Id'] = os.path.split(path)[1].split('.')[0]
|
||||
mod_info['Version'] = info['version'] if 'version' in info_keys else 'None'
|
||||
mod_info['DisplayName_CN'] = info['name'] if 'name' in info_keys else 'None'
|
||||
mod_info['DisplayName_EN'] = info['name_EN'] if 'name_EN' in info_keys else 'None'
|
||||
mod_info['FilePath'] = os.path.join(os.path.split(path)[1].split('.')[0],mods[0])#仅添加第一个找到的skudef文件
|
||||
mod_info['Desc_CN'] = info['introduce'] if 'introduce' in info_keys else 'None'
|
||||
mod_info['Desc_EN'] = info['introduce_EN'] if 'introduce_EN' in info_keys else 'None'
|
||||
with open(os.path.join(outpath,'config.json'),'w') as file:
|
||||
json.dump(mod_info,file)
|
||||
except Exception as err:
|
||||
QMessageBox.warning(self,'生成失败','生成失败,原因:{}'.format(err),QMessageBox.Ok,QMessageBox.Ok)
|
||||
return
|
||||
else:
|
||||
QMessageBox.information(self,'生成成功','生成成功',QMessageBox.Ok,QMessageBox.Ok)
|
||||
def download_err(self,err:Exception):
|
||||
self.isdownloading = False
|
||||
os.remove(self.download_info[1])
|
||||
self.progressBar_Download.setValue(0)
|
||||
self.pushButton_Download.setText('下载')
|
||||
QMessageBox.warning(self,'下载失败','下载失败,原因:{}'.format(err),QMessageBox.Ok,QMessageBox.Ok)
|
||||
def set_new_version(self,version:str):
|
||||
self.label_about_newverison.setText("最新版本:"+version)
|
||||
@ -333,12 +407,62 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
self_version = int(self.version.replace('.',''))
|
||||
if version_int > self_version:
|
||||
self.label_about_newverison.setText("<font color=red>最新版本:"+version+"(有更新!请点击发布页下载)</font>")
|
||||
self.setStatusTip('有新版本!({})'.format(version))
|
||||
def get_new_version_err(self,err:str):
|
||||
self.label_about_newverison.setText("<font color=red>最新版本:连接到纯世蜉生失败,原因:{}</font>".format(err))
|
||||
def __on_pushButton_release_clicked(self):
|
||||
webbrowser.open('https://cloud.armorrush.com/Hatanezumi/RA3_affiliated_mod_downloader/releases')
|
||||
def set_plainTextEdit_updatelog(self,text:str):
|
||||
self.plainTextEdit_updatelog.setPlainText(text)
|
||||
def __on_pushButton_changeDir_RA3_clicked(self):
|
||||
if self.ra3_path == '':
|
||||
self.pushButton_changeDir_RA3.setEnabled(False)
|
||||
return
|
||||
mods = AutoProcess.get_mods(self.ra3_path)
|
||||
if mods[0] is False:
|
||||
QMessageBox.warning(self,'获取mod列表失败',mods[1],QMessageBox.Ok,QMessageBox.Ok)
|
||||
else:
|
||||
self.base_mod_path = self.ra3_path
|
||||
self.mods = mods
|
||||
Process.set_comboBox(self.comboBox_mods,[os.path.splitext(os.path.split(mod_name)[1])[0] for mod_name in mods[1]])
|
||||
#显示当前目录
|
||||
self.lineEdit_nowpath.setText(self.ra3_path)
|
||||
def __on_pushButton_changeDir_mod_clicked(self):
|
||||
self.documents_path, self.base_mod_path = AutoProcess.get_mod_path()
|
||||
mods = AutoProcess.get_mods(self.base_mod_path)
|
||||
if mods[0] is False:
|
||||
QMessageBox.warning(self,'获取mod列表失败',mods[1],QMessageBox.Ok,QMessageBox.Ok)
|
||||
else:
|
||||
self.mods = mods
|
||||
Process.set_comboBox(self.comboBox_mods,[os.path.splitext(os.path.split(mod_name)[1])[0] for mod_name in mods[1]])
|
||||
#显示当前目录
|
||||
self.lineEdit_nowpath.setText(self.base_mod_path)
|
||||
def __on_pushButton_localRefresh_clicked(self):
|
||||
currentIndex = self.comboBox_mods.currentIndex()
|
||||
now_path = self.lineEdit_nowpath.text()
|
||||
if os.path.exists(now_path) is False:
|
||||
self.__on_pushButton_changeDir_mod_clicked()
|
||||
return
|
||||
mods = AutoProcess.get_mods(now_path)
|
||||
if mods[0] is False:
|
||||
QMessageBox.warning(self,'获取mod列表失败',mods[1],QMessageBox.Ok,QMessageBox.Ok)
|
||||
else:
|
||||
self.base_mod_path = now_path
|
||||
self.mods = mods
|
||||
Process.set_comboBox(self.comboBox_mods,[os.path.splitext(os.path.split(mod_name)[1])[0] for mod_name in mods[1]])
|
||||
#显示当前目录
|
||||
self.lineEdit_nowpath.setText(now_path)
|
||||
if currentIndex + 1 > self.comboBox_mods.count():
|
||||
return
|
||||
else:
|
||||
self.comboBox_mods.setCurrentIndex(currentIndex)
|
||||
def __on_pushButton_changeDir_ARModLauncher_clicked(self):
|
||||
if self.ARModLauncher_path == '':
|
||||
self.pushButton_changeDir_ARModLauncher.setEnabled(False)
|
||||
return
|
||||
self.lineEdit_savedir.setText(self.ARModLauncher_path)
|
||||
def init():
|
||||
app = QApplication(sys.argv)
|
||||
main_window = MainWindow()
|
||||
main_window.show()
|
||||
sys.exit(app.exec_())
|
||||
sys.exit(app.exec_())
|
||||
|
@ -3,7 +3,7 @@
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'MainWindow.ui'
|
||||
##
|
||||
## Created by: Qt User Interface Compiler version 6.4.2
|
||||
## Created by: Qt User Interface Compiler version 6.5.1
|
||||
##
|
||||
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
################################################################################
|
||||
@ -43,11 +43,11 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.verticalLayout_3.addWidget(self.label_local)
|
||||
|
||||
self.listView_loacl = QListView(self.tab_local)
|
||||
self.listView_loacl.setObjectName(u"listView_loacl")
|
||||
self.listView_loacl.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.listView_local = QListView(self.tab_local)
|
||||
self.listView_local.setObjectName(u"listView_local")
|
||||
self.listView_local.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
|
||||
self.verticalLayout_3.addWidget(self.listView_loacl)
|
||||
self.verticalLayout_3.addWidget(self.listView_local)
|
||||
|
||||
|
||||
self.horizontalLayout.addLayout(self.verticalLayout_3)
|
||||
@ -126,6 +126,21 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.verticalLayout_4.addLayout(self.horizontalLayout_6)
|
||||
|
||||
self.horizontalLayout_8 = QHBoxLayout()
|
||||
self.horizontalLayout_8.setObjectName(u"horizontalLayout_8")
|
||||
self.pushButton_changeDir_RA3 = QPushButton(self.tab_local)
|
||||
self.pushButton_changeDir_RA3.setObjectName(u"pushButton_changeDir_RA3")
|
||||
|
||||
self.horizontalLayout_8.addWidget(self.pushButton_changeDir_RA3)
|
||||
|
||||
self.pushButton_changeDir_mod = QPushButton(self.tab_local)
|
||||
self.pushButton_changeDir_mod.setObjectName(u"pushButton_changeDir_mod")
|
||||
|
||||
self.horizontalLayout_8.addWidget(self.pushButton_changeDir_mod)
|
||||
|
||||
|
||||
self.verticalLayout_4.addLayout(self.horizontalLayout_8)
|
||||
|
||||
self.comboBox_mods = QComboBox(self.tab_local)
|
||||
self.comboBox_mods.setObjectName(u"comboBox_mods")
|
||||
|
||||
@ -140,6 +155,11 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.verticalLayout_4.addItem(self.verticalSpacer)
|
||||
|
||||
self.pushButton_localRefresh = QPushButton(self.tab_local)
|
||||
self.pushButton_localRefresh.setObjectName(u"pushButton_localRefresh")
|
||||
|
||||
self.verticalLayout_4.addWidget(self.pushButton_localRefresh)
|
||||
|
||||
self.pushButton_save = QPushButton(self.tab_local)
|
||||
self.pushButton_save.setObjectName(u"pushButton_save")
|
||||
|
||||
@ -200,6 +220,7 @@ class Ui_MainWindow(object):
|
||||
self.plainTextEdit_introduce = QPlainTextEdit(self.tab_Network)
|
||||
self.plainTextEdit_introduce.setObjectName(u"plainTextEdit_introduce")
|
||||
self.plainTextEdit_introduce.setLineWrapMode(QPlainTextEdit.NoWrap)
|
||||
self.plainTextEdit_introduce.setReadOnly(True)
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.plainTextEdit_introduce)
|
||||
|
||||
@ -255,6 +276,11 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.verticalLayout_8.addLayout(self.horizontalLayout_7)
|
||||
|
||||
self.pushButton_changeDir_ARModLauncher = QPushButton(self.tab_Network)
|
||||
self.pushButton_changeDir_ARModLauncher.setObjectName(u"pushButton_changeDir_ARModLauncher")
|
||||
|
||||
self.verticalLayout_8.addWidget(self.pushButton_changeDir_ARModLauncher)
|
||||
|
||||
self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout_8.addItem(self.verticalSpacer_3)
|
||||
@ -312,6 +338,18 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.verticalLayout_10.addWidget(self.label_about_newverison)
|
||||
|
||||
self.label_updatelog = QLabel(self.tab_about)
|
||||
self.label_updatelog.setObjectName(u"label_updatelog")
|
||||
|
||||
self.verticalLayout_10.addWidget(self.label_updatelog)
|
||||
|
||||
self.plainTextEdit_updatelog = QPlainTextEdit(self.tab_about)
|
||||
self.plainTextEdit_updatelog.setObjectName(u"plainTextEdit_updatelog")
|
||||
self.plainTextEdit_updatelog.setLineWrapMode(QPlainTextEdit.NoWrap)
|
||||
self.plainTextEdit_updatelog.setReadOnly(True)
|
||||
|
||||
self.verticalLayout_10.addWidget(self.plainTextEdit_updatelog)
|
||||
|
||||
self.pushButton_release = QPushButton(self.tab_about)
|
||||
self.pushButton_release.setObjectName(u"pushButton_release")
|
||||
|
||||
@ -351,7 +389,10 @@ class Ui_MainWindow(object):
|
||||
self.pushButton_L.setText(QCoreApplication.translate("MainWindow", u"-", None))
|
||||
self.label_nowpath.setText(QCoreApplication.translate("MainWindow", u"\u5f53\u524d\u76ee\u5f55:", None))
|
||||
self.pushButton_nowpath.setText(QCoreApplication.translate("MainWindow", u"...", None))
|
||||
self.pushButton_changeDir_RA3.setText(QCoreApplication.translate("MainWindow", u"\u5207\u6362\u5230RA3\u76ee\u5f55", None))
|
||||
self.pushButton_changeDir_mod.setText(QCoreApplication.translate("MainWindow", u"\u5207\u6362\u5230mod\u76ee\u5f55", None))
|
||||
self.label_nowdir.setText(QCoreApplication.translate("MainWindow", u"\u5f53\u524d\u6587\u4ef6\u5939:", None))
|
||||
self.pushButton_localRefresh.setText(QCoreApplication.translate("MainWindow", u"\u5237\u65b0", None))
|
||||
self.pushButton_save.setText(QCoreApplication.translate("MainWindow", u"\u4fdd\u5b58", None))
|
||||
self.tabWidget_Main.setTabText(self.tabWidget_Main.indexOf(self.tab_local), QCoreApplication.translate("MainWindow", u"\u672c\u5730", None))
|
||||
self.pushButton_refresh.setText(QCoreApplication.translate("MainWindow", u"\u5237\u65b0", None))
|
||||
@ -362,12 +403,14 @@ class Ui_MainWindow(object):
|
||||
self.label_savedir.setText(QCoreApplication.translate("MainWindow", u"\u4fdd\u5b58\u5230:", None))
|
||||
self.pushButton_savedir.setText(QCoreApplication.translate("MainWindow", u"...", None))
|
||||
self.label_source.setText(QCoreApplication.translate("MainWindow", u"\u4e0b\u8f7d\u6e90:", None))
|
||||
self.pushButton_changeDir_ARModLauncher.setText(QCoreApplication.translate("MainWindow", u"\u5207\u6362\u5230AR\u542f\u52a8\u5668\u76ee\u5f55", None))
|
||||
self.pushButton_Download.setText(QCoreApplication.translate("MainWindow", u"\u4e0b\u8f7d", None))
|
||||
self.tabWidget_Main.setTabText(self.tabWidget_Main.indexOf(self.tab_Network), QCoreApplication.translate("MainWindow", u"\u7f51\u7edc", None))
|
||||
self.label_about_author.setText(QCoreApplication.translate("MainWindow", u"\u4f5c\u8005:\u7530\u9f20-Hatanezumi", None))
|
||||
self.label_about_contact.setText(QCoreApplication.translate("MainWindow", u"\u8054\u7cfb:Hatanezumi@chunshengserver.cn", None))
|
||||
self.label_about_verison.setText(QCoreApplication.translate("MainWindow", u"\u5f53\u524d\u7248\u672c:", None))
|
||||
self.label_about_newverison.setText(QCoreApplication.translate("MainWindow", u"\u6700\u65b0\u7248\u672c:", None))
|
||||
self.label_updatelog.setText(QCoreApplication.translate("MainWindow", u"\u66f4\u65b0\u65e5\u5fd7:", None))
|
||||
self.pushButton_release.setText(QCoreApplication.translate("MainWindow", u"\u53d1\u5e03\u9875", None))
|
||||
self.tabWidget_Main.setTabText(self.tabWidget_Main.indexOf(self.tab_about), QCoreApplication.translate("MainWindow", u"\u5173\u4e8e", None))
|
||||
#if QT_CONFIG(statustip)
|
||||
|
@ -38,7 +38,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="listView_loacl">
|
||||
<widget class="QListView" name="listView_local">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
@ -134,6 +134,24 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_changeDir_RA3">
|
||||
<property name="text">
|
||||
<string>切换到RA3目录</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_changeDir_mod">
|
||||
<property name="text">
|
||||
<string>切换到mod目录</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_mods"/>
|
||||
</item>
|
||||
@ -157,6 +175,13 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_localRefresh">
|
||||
<property name="text">
|
||||
<string>刷新</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_save">
|
||||
<property name="text">
|
||||
@ -241,6 +266,9 @@
|
||||
<property name="lineWrapMode">
|
||||
<enum>QPlainTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -295,6 +323,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_changeDir_ARModLauncher">
|
||||
<property name="text">
|
||||
<string>切换到AR启动器目录</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
@ -372,6 +407,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_updatelog">
|
||||
<property name="text">
|
||||
<string>更新日志:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit_updatelog">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QPlainTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_release">
|
||||
<property name="text">
|
||||
|
Binary file not shown.
@ -1,2 +1,2 @@
|
||||
pyside2-uic [你保存的文件名].ui > ***.py
|
||||
pyside6-uic [你保存的文件名].ui > ***.py
|
||||
另外别忘了将生成的文件另存为utf-8
|
16
更新日志.txt
Normal file
16
更新日志.txt
Normal file
@ -0,0 +1,16 @@
|
||||
[1.1.0]
|
||||
1.支持终止下载
|
||||
2.添加下载超时中断功能
|
||||
3.可以自动识别到AR启动器并可以切换到对应的目录
|
||||
4.如在AR启动器的目录内则可以生成能被AR启动器识别的附属mod配置文件
|
||||
[1.0.3]
|
||||
1.支持识别RA3目录
|
||||
2.添加了切换到RA3目录和mod目录按钮
|
||||
3.添加了本地刷新按钮
|
||||
[1.0.2]
|
||||
1.更改了下载完成后的信息框样式
|
||||
2.可以在状态栏显示是否有新版本
|
||||
[1.0.1]
|
||||
1.修复了下载完成后无反馈及无自动解压的问题
|
||||
2.修复了"我的文档"在其他目录无法识别的问题
|
||||
3.添加了更新日志功能
|
Loading…
x
Reference in New Issue
Block a user