Skip to content

Commit

Permalink
Merge pull request #43 from Wolfmyths/future-update
Browse files Browse the repository at this point in the history
1.3.0
  • Loading branch information
Wolfmyths authored Dec 5, 2023
2 parents 6eb9105 + c4592e4 commit 2e40bfa
Show file tree
Hide file tree
Showing 36 changed files with 614 additions and 178 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ MANIFEST
config.ini
mods.ini
profiles.json
externalshortcuts.json

# Disabled Mods Directory
disabled-mods/
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ A simple mod manager for PAYDAY 2 to make managing all of those files a little b
* Disable mods you don't want to use at the moment.
+ *This feature is good for testing out which mod is crashing the game!*

* External tools tab to have shortcuts to modding tools in one place

* Search bar to find the installed mod you're looking for in seconds.

* Create profiles to organize your mods.
Expand Down Expand Up @@ -74,8 +76,7 @@ Windows:

Linux/MacOS:

+ There are plans to add support for Linux/MacOS
- If you are experienced with either OS, help is wanted at this github issue: https://github.com/Wolfmyths/Myth-Mod-Manager/issues/18
If you are an avid Linux user you may be able to help create compadability for MacOS/Linux on [this issue here](https://github.com/Wolfmyths/Myth-Mod-Manager/issues/18)

### Reguarding Storefront

Expand All @@ -86,8 +87,8 @@ You may download any version of Myth Mod Manager and view changelogs at the [rel

# Future Plans

+ Rewrite Settings UI
+ New Icon/Logo
+ Duplicate mod detection
+ Auto mod type detection
+ Linux support
+ Some kind of [modworkshop.net](https://modworkshop.net/g/payday-2) integration, see [issue #14](https://github.com/Wolfmyths/Myth-Mod-Manager/issues/14)
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "src"
version = "1.2.3"
version = "1.3.0"
description = "A PAYDAY 2 Mod Manager"
authors = ["Wolfmyths"]
license = "MIT"
Expand All @@ -11,6 +11,7 @@ python = "^3.11"
PySide6 = "6.6.0"
patool = "1.12"
semantic-version = "2.10.0"
Pyinstaller = "6.2.0"

[build-system]
requires = ["poetry-core"]
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ semantic-version==2.10.0
patool==1.12.0

# For external purposes
pyinstaller==6.1.0
pyinstaller==6.2.0
pytest==7.4.2
pytest-qt==4.2.0
5 changes: 4 additions & 1 deletion src/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import xml.etree.ElementTree as et
import logging
from typing import Any

from semantic_version import Version

Expand All @@ -25,13 +26,15 @@ def __loadXML(modPath: str) -> et.ElementTree | None:

return xml

def __parseVersion(version: str) -> Version | None:
def __parseVersion(version: Any) -> Version | None:

logging.debug('Parsing %s', version)

if version is None:
return

version: str = str(version)

removeChars = ('v', 'V')
try:
if version.startswith(removeChars):
Expand Down
9 changes: 8 additions & 1 deletion src/api/checkUpdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ class checkUpdate(QObject):
'''

updateDetected = Signal(str, str)
upToDate = Signal()
error = Signal()

def __init__(self) -> None:
super().__init__()
logging.getLogger(__file__)

link = 'https://api.github.com/repos/Wolfmyths/Myth-Mod-Manager/releases'

Expand All @@ -29,6 +32,7 @@ def __init__(self) -> None:

network = QNetworkAccessManager(self)
request = QNetworkRequest(QUrl(link))
logging.debug('Request for %s from checkUpdate() started', link)

self.reply = network.get(request)
self.reply.finished.connect(self.__reply_handler)
Expand All @@ -40,6 +44,7 @@ def __reply_handler(self) -> None:
self.__checkVersion()
else:
logging.error('Internet error in checkUpdate():\n%s', reply.error())
self.error.emit()

def __checkVersion(self) -> None:
reply: QNetworkReply = self.sender()
Expand All @@ -48,6 +53,7 @@ def __checkVersion(self) -> None:
data: dict = json.loads(reply.readAll().data().decode())
except Exception as e:
logging.error('An error occured trying to access a Github API reply in checkUpdate().__checkversion():\n%s', str(e))
self.error.emit()
return

if isPrerelease(VERSION):
Expand All @@ -59,6 +65,7 @@ def __checkVersion(self) -> None:

if latestVersion > VERSION:
self.updateDetected.emit(latestVersion, data['body'])
else:
self.upToDate.emit()

self.deleteLater()

14 changes: 8 additions & 6 deletions src/constant_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ class OptionKeys(StrEnum):

section = 'OPTIONS' # Main section

game_path = auto()
dispath = 'disabled-mods'
color_theme = auto()
windowsize_w = auto()
windowsize_h = auto()
game_path = auto()
dispath = 'disabled-mods'
color_theme = auto()
windowsize_w = auto()
windowsize_h = auto()
mmm_update_alert = auto()

class ProfileRole():

Expand All @@ -55,6 +56,7 @@ class ProfileRole():
MOD_CONFIG = 'mods.ini'
OPTIONS_CONFIG = 'config.ini'
PROFILES_JSON = 'profiles.json'
TOOLS_JSON = 'externalshortcuts.json'
START_PAYDAY = 'runGame.bat'
OLD_EXE = 'Myth Mod Manager.exe (Old)'
DISABLED_MODS = 'disabled-mods'
Expand Down Expand Up @@ -94,4 +96,4 @@ class ProfileRole():
# Program Info
PROGRAM_NAME = 'Myth Mod Manager'

VERSION = semantic_version.Version(major=1, minor=2, patch=3)
VERSION = semantic_version.Version(major=1, minor=3, patch=0)
11 changes: 7 additions & 4 deletions src/main_window.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import os


import PySide6.QtGui as qtg
import PySide6.QtWidgets as qtw
from PySide6.QtCore import QCoreApplication

from src.manager import ModManager
from src.tools import ToolManager
from src.settings import Options
from src.profiles import modProfile
from src.widgets.aboutQWidget import About
Expand Down Expand Up @@ -33,6 +33,7 @@ def __init__(self, app: qtw.QApplication | None = None, savePath = MOD_CONFIG, o

self.manager = ModManager(savePath, optionsPath)
self.profile = modProfile()
self.tools = ToolManager()
self.options = Options()
self.about = About()

Expand All @@ -46,6 +47,7 @@ def __init__(self, app: qtw.QApplication | None = None, savePath = MOD_CONFIG, o
for page in (
(self.manager, 'Manager'),
(self.profile, 'Profiles'),
(self.tools, 'Tools'),
(self.options, 'Options'),
(self.about, 'About')
):
Expand All @@ -54,10 +56,11 @@ def __init__(self, app: qtw.QApplication | None = None, savePath = MOD_CONFIG, o

self.setCentralWidget(self.tab)

run_checkUpdate = checkUpdate()
run_checkUpdate.updateDetected.connect(lambda x, y: self.updateDetected(x, y))
if self.optionsManager.getMMMUpdateAlert():
self.run_checkUpdate = checkUpdate()
self.run_checkUpdate.updateDetected.connect(lambda x, y: self.updateDetected(x, y))

def updateDetected(latestVersion: str, changelog: str) -> None:
def updateDetected(self, latestVersion: str, changelog: str) -> None:
notice = updateDetected(latestVersion, changelog)
notice.exec()

Expand Down
29 changes: 19 additions & 10 deletions src/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def __newMod(self, mod: str, type: ModType) -> None:
'''

if not self.has_section(mod):
logging.info('Adding mod: %s', mod)
self.add_section(mod)

self.setEnabled(mod)
Expand Down Expand Up @@ -126,14 +127,15 @@ def setModWorkshopAssetID(self, mod: str, id: str = '') -> None:
def removeMods(self, *mods: str) -> None:
'''Removes mods from MOD_CONFIG'''

for mod in mods:
logging.info('Removing mod(s): %s', ', '.join(mods))

for mod in mods:
self.remove_section(mod)

def clearModData(self) -> None:
'''Wipes the MOD_CONFIG's data'''

logging.info('DELETING MODS FROM %s', MOD_CONFIG)
logging.info('DELETING ALL MODS FROM %s', MOD_CONFIG)

self.clear()

Expand All @@ -145,37 +147,44 @@ def __init__(self, file=OPTIONS_CONFIG):

if not self.has_section(OptionKeys.section.value):
self.add_section(OptionKeys.section.value)

def hasOption(self, option: str) -> bool:
return self.has_option(OptionKeys.section.value, option)

def getMMMUpdateAlert(self) -> bool:
self.def_read()
return self.getboolean(OptionKeys.section.value, OptionKeys.mmm_update_alert, fallback=True)

def setMMMUpdateAlert(self, alert: bool = True) -> None:
self.set(OptionKeys.section.value, OptionKeys.mmm_update_alert.name, str(alert))

def getTheme(self) -> str:
self.def_read()
return self.get(OptionKeys.section, OptionKeys.color_theme, fallback=LIGHT)

def setTheme(self, theme: str = LIGHT) -> None:
self.set(OptionKeys.section.value, OptionKeys.color_theme.value, theme)

def getGamepath(self) -> str:
self.def_read()
return self.get(OptionKeys.section.value, OptionKeys.game_path, fallback='')

def setGamepath(self, path: str = '') -> None:
self.set(OptionKeys.section.value, OptionKeys.game_path.name, path)

def getDispath(self) -> str:
self.def_read()
return self.get(OptionKeys.section, OptionKeys.dispath, fallback=MODS_DISABLED_PATH_DEFAULT)

def setDispath(self, path: str = MODS_DISABLED_PATH_DEFAULT) -> None:
self.set(OptionKeys.section.value, OptionKeys.dispath.value, path)

def getWindowSize(self) -> QSize:
self.def_read()
width = self.getint(OptionKeys.section, OptionKeys.windowsize_w, fallback=800)
height = self.getint(OptionKeys.section, OptionKeys.windowsize_h, fallback=800)
return QSize(width, height)

def setWindowSize(self, size: QSize = QSize(800, 800)) -> None:
self.set(OptionKeys.section.value, OptionKeys.windowsize_w.value, str(size.width()))
self.set(OptionKeys.section.value, OptionKeys.windowsize_h.value, str(size.height()))
38 changes: 36 additions & 2 deletions src/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
import logging

import PySide6.QtWidgets as qtw
from PySide6.QtCore import QCoreApplication

from src.widgets.progressWidget import ProgressWidget
from src.threaded.backupMods import BackupMods
from src.save import OptionsManager
from src.getPath import Pathing
from src.style import StyleManager
from src.widgets.ignoredModsQListWidget import IgnoredMods
from src.constant_vars import DARK, LIGHT, OPTIONS_CONFIG
from src.constant_vars import DARK, LIGHT, OPTIONS_CONFIG, ROOT_PATH
from src.widgets.QDialog.newUpdateQDialog import updateDetected

from src.api.checkUpdate import checkUpdate

class Options(qtw.QWidget):

Expand All @@ -25,6 +29,13 @@ def __init__(self, optionsPath = OPTIONS_CONFIG) -> None:

self.optionsManager = OptionsManager(optionsPath)

self.updateAlertCheckbox = qtw.QCheckBox(self, text='Update alerts on startup')
self.updateAlertCheckbox.setChecked(self.optionsManager.getMMMUpdateAlert())
self.updateAlertCheckbox.clicked.connect(self.setUpdateAlert)

self.checkUpdateButton = qtw.QPushButton(self, text='Check for updates')
self.checkUpdateButton.clicked.connect(self.checkUpdate)

self.gameDirLabel = qtw.QLabel(self, text='Payday 2 Game Path:')

self.gameDir = qtw.QLineEdit(self)
Expand Down Expand Up @@ -84,7 +95,8 @@ def __init__(self, optionsPath = OPTIONS_CONFIG) -> None:
self.modLog = qtw.QPushButton(parent=self, text='Mod Crash Logs')
self.modLog.clicked.connect(lambda: self.openCrashLogBLT())

for row in ( (self.gameDirLabel, self.gameDir),
for row in ( (self.updateAlertCheckbox, self.checkUpdateButton),
(self.gameDirLabel, self.gameDir),
(self.disabledModLabel, self.disabledModDir),
(self.ignoredModsLabel, self.ignoredModsListWidget),
(self.backupModsLabel, self.backupMods),
Expand All @@ -95,6 +107,28 @@ def __init__(self, optionsPath = OPTIONS_CONFIG) -> None:
layout.addRow(row[0], row[1])

self.setLayout(layout)

def setUpdateAlert(self) -> None:
alert = self.updateAlertCheckbox.isChecked()
self.optionsManager.setMMMUpdateAlert(alert)
self.optionsManager.writeData()

def checkUpdate(self) -> None:
def updateFound(latestVersion: str, changelog: str) -> None:
notice = updateDetected(latestVersion, changelog)
notice.rejected.connect(lambda: self.checkUpdateButton.setText('Check for updates'))
notice.exec()

if notice.result():
os.startfile(os.path.join(ROOT_PATH, 'Myth Mod Manager.exe'))
QCoreApplication.quit()

self.checkUpdateButton.setText('Checking...')

self.run_checkupdate = checkUpdate()
self.run_checkupdate.updateDetected.connect(lambda x, y: updateFound(x, y))
self.run_checkupdate.error.connect(lambda: self.checkUpdateButton.setText('Error: Check logs for more info'))
self.run_checkupdate.upToDate.connect(lambda: self.checkUpdateButton.setText('Up to date! ^_^'))

def openCrashLogBLT(self) -> None:
modPath = Pathing().mods()
Expand Down
12 changes: 12 additions & 0 deletions src/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,18 @@ class StyleManager():
QGroupBox {{
border: 15px solid {0};
}}
QFrame#externaltool {{
background-color: {2};
border: 2px solid {3};
border-radius: 4px;
padding: 2px;
}}
QFrame#optionsframe {{
background-color: {2};
border: none;
}}
'''

def __init__(self) -> None:
Expand Down
2 changes: 0 additions & 2 deletions src/threaded/backupMods.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ def backupMods(self) -> None:

os.mkdir(path)

print(self.bundledFilePath, os.path.isfile(self.bundledFilePath))

# Because this dir is a nested one, needs os.makedirs unlike the others
if not os.path.isdir(bundledOverridePath):

Expand Down
1 change: 1 addition & 0 deletions src/threaded/changeModType.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
class ChangeModType(FileMover):
def __init__(self, *mods: tuple[str, ModType]):
super().__init__()
logging.getLogger(__name__)

self.mods = mods

Expand Down
Loading

0 comments on commit 2e40bfa

Please sign in to comment.