Move source code to src/leek
This makes the package work again
This commit is contained in:
parent
1a626fddff
commit
6061590270
9 changed files with 16 additions and 10 deletions
90
src/leek/Main.qml
Normal file
90
src/leek/Main.qml
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls as Controls
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
Kirigami.ApplicationWindow {
|
||||
id: root
|
||||
title: "Leek"
|
||||
|
||||
pageStack.initialPage: Kirigami.ScrollablePage {
|
||||
title: "Mods"
|
||||
Kirigami.CardsListView {
|
||||
id: modsView
|
||||
model: modListModel
|
||||
delegate: modCardDelegate
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: modCardDelegate
|
||||
Kirigami.AbstractCard {
|
||||
// headerOrientation: Qt.Horizontal
|
||||
contentItem: Item {
|
||||
implicitWidth: modCardLayout.implicitWidth
|
||||
implicitHeight: modCardLayout.implicitHeight
|
||||
GridLayout {
|
||||
id: modCardLayout
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
rowSpacing: Kirigami.Units.largeSpacing
|
||||
columnSpacing: Kirigami.Units.largeSpacing
|
||||
columns: root.wideScreen ? 4 : 2
|
||||
|
||||
// TODO: Replace this with an image once we can get them
|
||||
Controls.BusyIndicator {
|
||||
running: true
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Kirigami.Heading {
|
||||
Layout.fillWidth: true
|
||||
text: name
|
||||
type: Kirigami.Heading.Type.Primary
|
||||
}
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: description ? description : "No description available"
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Controls.Switch {
|
||||
text: "Enabled"
|
||||
checked: true
|
||||
}
|
||||
Controls.Button {
|
||||
text: "Delete"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: modListModel
|
||||
ListElement {
|
||||
name: "DivaNoSpy"
|
||||
description: "Disables project diva's telemetry"
|
||||
}
|
||||
ListElement {
|
||||
name: "exPatch"
|
||||
description: "Unlocks extreme difficulty immediately"
|
||||
}
|
||||
ListElement {
|
||||
name: "Mod with no description"
|
||||
}
|
||||
ListElement {
|
||||
name: "Very long description"
|
||||
description: "前奏で胸倉掴まれてサビでぶん殴られたわ、何このバイオレンス曲
|
||||
「初音ミクに決まってんだろ」とかこんな直球でボカロ主張してくる曲多くないから最高。誰か救急車呼んで(吐血)"
|
||||
}
|
||||
}
|
||||
}
|
||||
0
src/leek/__init__.py
Normal file
0
src/leek/__init__.py
Normal file
14
src/leek/__main__.py
Normal file
14
src/leek/__main__.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/#running-a-command-line-interface-from-source-with-src-layout
|
||||
import os
|
||||
import sys
|
||||
|
||||
if not __package__:
|
||||
# Make CLI runnable from source tree with
|
||||
# python src/package
|
||||
package_source_path = os.path.dirname(os.path.dirname(__file__))
|
||||
sys.path.insert(0, package_source_path)
|
||||
|
||||
|
||||
from leek import leek_app
|
||||
|
||||
leek_app.main()
|
||||
36
src/leek/leek_app.py
Normal file
36
src/leek/leek_app.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
from PySide6.QtGui import QGuiApplication
|
||||
from PySide6.QtCore import QUrl
|
||||
from PySide6.QtQml import QQmlApplicationEngine
|
||||
|
||||
|
||||
def main():
|
||||
"""Initializes and manages the application execution"""
|
||||
app: QGuiApplication = QGuiApplication(sys.argv)
|
||||
app.setDesktopFileName("xyz.toast003.leek")
|
||||
app.setApplicationName("Leek")
|
||||
engine = QQmlApplicationEngine()
|
||||
|
||||
"""Needed to close the app with Ctrl+C"""
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
"""Needed to get proper KDE style outside of Plasma"""
|
||||
if not os.environ.get("QT_QUICK_CONTROLS_STYLE"):
|
||||
os.environ["QT_QUICK_CONTROLS_STYLE"] = "org.kde.desktop"
|
||||
|
||||
base_path = os.path.abspath(os.path.dirname(__file__))
|
||||
url = QUrl(f"file://{base_path}/Main.qml")
|
||||
engine.load(url)
|
||||
|
||||
if len(engine.rootObjects()) == 0:
|
||||
quit()
|
||||
|
||||
app.exec()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
71
src/leek/mod.py
Normal file
71
src/leek/mod.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import tomlkit
|
||||
|
||||
|
||||
class Mod:
|
||||
@property
|
||||
def path(self) -> str:
|
||||
return self.__path
|
||||
|
||||
# Mod metadata
|
||||
@property
|
||||
def name(self) -> str | None:
|
||||
if "name" not in self.__config:
|
||||
return None
|
||||
return self.__config["name"].as_string()
|
||||
|
||||
@property
|
||||
def description(self) -> str | None:
|
||||
if "description" not in self.__config.keys():
|
||||
return None
|
||||
else:
|
||||
return self.__config["description"].as_string()
|
||||
|
||||
@property
|
||||
def author(self) -> str | None:
|
||||
if "author" not in self.__config:
|
||||
return None
|
||||
return self.__config["author"].as_string()
|
||||
|
||||
@property
|
||||
def enabled(self) -> bool:
|
||||
return True if self.__enabled == "true" else False
|
||||
|
||||
@enabled.setter
|
||||
def enabled(self, value: bool) -> None:
|
||||
if value == self.__enabled:
|
||||
# Nothing to do
|
||||
return
|
||||
|
||||
with open(self.__path + "config.toml", "w") as config_file:
|
||||
self.__config["enabled"] = value
|
||||
tomlkit.dump(self.__config, config_file)
|
||||
|
||||
def __init__(self, path: str) -> None:
|
||||
self.__path = path
|
||||
|
||||
try:
|
||||
with open(path + "config.toml") as config_file:
|
||||
self.__config = tomlkit.load(config_file)
|
||||
|
||||
if "enabled" not in self.__config:
|
||||
raise InvalidModError("config.toml does not contain the enabled key")
|
||||
else:
|
||||
self.__enabled = self.__config["enabled"]
|
||||
except FileNotFoundError:
|
||||
raise InvalidModError("config.toml does not exist")
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Mod({self.__path})"
|
||||
|
||||
|
||||
class InvalidModError(Exception):
|
||||
"""
|
||||
This exception is raised when the Mod class gets given a path of something that's not a valid mod
|
||||
"""
|
||||
|
||||
def __init__(self, message: str) -> None:
|
||||
super().__init__(message)
|
||||
self.message = message
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.message}"
|
||||
54
src/leek/mod_list.py
Normal file
54
src/leek/mod_list.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
from PySide6.QtQml import QmlElement
|
||||
from PySide6.QtCore import QAbstractListModel, QModelIndex
|
||||
from leek.mod import Mod, InvalidModError
|
||||
import os
|
||||
|
||||
QML_IMPORT_NAME = "Leek"
|
||||
QML_IMPORT_MAJOR_VERSION = 1
|
||||
|
||||
# TODO: Don't harcode the mods path
|
||||
GAME_PATH = "/home/toast/.local/share/Steam/steamapps/common/Hatsune Miku Project DIVA Mega Mix Plus/"
|
||||
|
||||
# Qt follows C++ naming conventions
|
||||
# ruff: noqa: N802
|
||||
@QmlElement
|
||||
class QModListModel(QAbstractListModel):
|
||||
def __init__(self, parent=None) -> None:
|
||||
super().__init__(parent=parent)
|
||||
mods: list[Mod] = []
|
||||
|
||||
with os.scandir(GAME_PATH + "mods/") as dirs:
|
||||
for dir in dirs:
|
||||
try:
|
||||
new_mod: Mod = Mod(dir.path + "/" )
|
||||
mods.append(new_mod)
|
||||
except InvalidModError as e:
|
||||
print(f"Found invalid mod at {dir.path}: {e.message}")
|
||||
continue
|
||||
|
||||
self.mods = mods
|
||||
|
||||
def roleNames(self) -> dict[int, bytes]:
|
||||
return {
|
||||
0: b"name",
|
||||
1: b"description",
|
||||
2: b"enabled"
|
||||
}
|
||||
|
||||
def rowCount(self, parent=QModelIndex()) -> int:
|
||||
return len(self.mods)
|
||||
|
||||
def data(self, index: QModelIndex, role: int) -> None | str | bool:
|
||||
i: int = index.row()
|
||||
result: None | str | bool
|
||||
if not index.isValid():
|
||||
result = None
|
||||
elif role == 0:
|
||||
result = self.mods[i].name
|
||||
elif role == 1:
|
||||
result = self.mods[i].description
|
||||
elif role == 2:
|
||||
result = self.mods[i].enabled
|
||||
else:
|
||||
result = None
|
||||
return result
|
||||
Loading…
Add table
Add a link
Reference in a new issue