1
0
Fork 0
mirror of synced 2024-06-26 18:20:50 +12:00

Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Dummerle 2021-04-11 21:49:03 +02:00
commit 10839623c6
15 changed files with 104 additions and 40 deletions

2
.github/GenPKG.sh vendored
View file

@ -1,5 +1,5 @@
export PYTHONPATH=$PWD export PYTHONPATH=$PWD
version=$(python3 Rare --version) version=$(python3 rare --version)
cd .github cd .github
git clone https://aur.archlinux.org/rare.git git clone https://aur.archlinux.org/rare.git
cd .. cd ..

View file

@ -1,12 +1,9 @@
# This workflow will upload a Python Package using Twine when a release
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: New Release name: New Release
on: on:
release: release:
types: [ published ] types: [ published ]
workflow_dispatch:
jobs: jobs:
pypy-deploy: pypy-deploy:
@ -61,9 +58,10 @@ jobs:
pip3 install pyinstaller setuptools wheel pip3 install pyinstaller setuptools wheel
pip3 install -r requirements.txt pip3 install -r requirements.txt
- name: Prepare - name: Prepare
run: cp Rare/__main__.py ./ run: cp rare/__main__.py ./
- name: Build - name: Build
run: pyinstaller run: pyinstaller
--icon=rare/styles/Logo.ico
--onefile --onefile
--name Rare --name Rare
--add-data="Rare/languages/*;Rare/languages" --add-data="Rare/languages/*;Rare/languages"
@ -91,7 +89,7 @@ jobs:
python3-requests python3-requests
python3-pyqt5 python3-pyqt5
python3-pil python3-pil
python3-qtawesome-common python3-qtawesome
python3-setuptools python3-setuptools
python3-wheel python3-wheel
@ -101,7 +99,7 @@ jobs:
python3 setup.py --command-packages=stdeb.command bdist_deb python3 setup.py --command-packages=stdeb.command bdist_deb
- name: move file - name: move file
run: mv deb_dist/*.deb rare.deb run: mv deb_dist/*.deb Rare.deb
- name: Upload files to GitHub - name: Upload files to GitHub
uses: svenstaro/upload-release-action@2.2.1 uses: svenstaro/upload-release-action@2.2.1

View file

@ -19,7 +19,8 @@ exmples:
Select one Card of the project and implement it or make other changes Select one Card of the project and implement it or make other changes
##Git crash-course ## Git crash-course
To contribute fork the repository and clone **your** repo. Then make your changes, add it to git with `git add .` and upload it to Github with `git commit -m "message"` and `git push` or with your IDE. To contribute fork the repository and clone **your** repo. Then make your changes, add it to git with `git add File.xy` and upload it to GitHub with `git commit -m "message"` and `git push`.
Some IDEs can do this automatically.
If you uploaded your changes, create a pull request If you uploaded your changes, create a pull request to dev-branch

View file

@ -1,3 +1,3 @@
include README.md include README.md
include rare/languages/de.qm include rare/languages/*.qm
include rare/styles/* include rare/styles/*

View file

@ -1,5 +1,5 @@
import os import os
__version__ = "1.0_beta2" __version__ = "1.0.0"
style_path = os.path.join(os.path.dirname(__file__), "styles/") style_path = os.path.join(os.path.dirname(__file__), "styles/")
lang_path = os.path.join(os.path.dirname(__file__), "languages/") lang_path = os.path.join(os.path.dirname(__file__), "languages/")

View file

@ -50,9 +50,9 @@ class DownloadTab(QWidget):
self.mini_layout.addWidget(self.prog_bar) self.mini_layout.addWidget(self.prog_bar)
self.kill_button = QPushButton(self.tr("Stop Download")) self.kill_button = QPushButton(self.tr("Stop Download"))
# self.mini_layout.addWidget(self.kill_button)
self.kill_button.setDisabled(True) self.kill_button.setDisabled(True)
self.kill_button.clicked.connect(self.stop_download) self.kill_button.clicked.connect(self.stop_download)
self.mini_layout.addWidget(self.kill_button)
self.layout.addLayout(self.mini_layout) self.layout.addLayout(self.mini_layout)
@ -85,7 +85,7 @@ class DownloadTab(QWidget):
self.dl_queue = dl_queue self.dl_queue = dl_queue
def stop_download(self): def stop_download(self):
self.thread.kill = True self.thread.kill()
def install_game(self, options: InstallOptions): def install_game(self, options: InstallOptions):
@ -227,11 +227,12 @@ class DownloadTab(QWidget):
else: else:
self.queue_widget.update_queue(self.dl_queue) self.queue_widget.update_queue(self.dl_queue)
elif text == "error": elif text[:5] == "error":
QMessageBox.warning(self, "warn", "Download error") QMessageBox.warning(self, "warn", "Download error: "+text[6:])
elif text == "stop": elif text == "stop":
self.reset_infos() self.reset_infos()
self.active_game = None
def reset_infos(self): def reset_infos(self):
self.kill_button.setDisabled(True) self.kill_button.setDisabled(True)

View file

@ -1,18 +1,19 @@
import os import os
import queue import queue
import subprocess import subprocess
import sys
import time import time
from logging import getLogger from logging import getLogger
from multiprocessing import Queue as MPQueue from multiprocessing import Queue as MPQueue
from queue import Empty
import psutil
from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
from rare.utils.models import KillDownloadException
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
from custom_legendary.downloader.manager import DLManager from custom_legendary.downloader.manager import DLManager
from custom_legendary.models.downloading import UIUpdate from custom_legendary.models.downloading import UIUpdate, WriterTask
logger = getLogger("Download") logger = getLogger("Download")
@ -20,7 +21,6 @@ logger = getLogger("Download")
class DownloadThread(QThread): class DownloadThread(QThread):
status = pyqtSignal(str) status = pyqtSignal(str)
statistics = pyqtSignal(UIUpdate) statistics = pyqtSignal(UIUpdate)
kill = False
def __init__(self, dlm: DLManager, core: LegendaryCore, status_queue: MPQueue, igame, repair=False, def __init__(self, dlm: DLManager, core: LegendaryCore, status_queue: MPQueue, igame, repair=False,
repair_file=None): repair_file=None):
@ -31,37 +31,92 @@ class DownloadThread(QThread):
self.igame = igame self.igame = igame
self.repair = repair self.repair = repair
self.repair_file = repair_file self.repair_file = repair_file
self._kill = False
def run(self): def run(self):
start_time = time.time() start_time = time.time()
dl_stopped = False
try: try:
self.dlm.start() self.dlm.start()
time.sleep(1) time.sleep(1)
while self.dlm.is_alive(): while self.dlm.is_alive():
if self.kill: if self._kill:
# raise KillDownloadException() self.status.emit("stop")
# TODO kill download queue, workers logger.info("Download stopping...")
pass
# The code below is a temporary solution.
# It should be removed once legendary supports stopping downloads more gracefully.
self.dlm.running = False
# send conditions to unlock threads if they aren't already
for cond in self.dlm.conditions:
with cond:
cond.notify()
# make sure threads are dead.
for t in self.dlm.threads:
t.join(timeout=5.0)
if t.is_alive():
logger.warning(f'Thread did not terminate! {repr(t)}')
# clean up all the queues, otherwise this process won't terminate properly
for name, q in zip(('Download jobs', 'Writer jobs', 'Download results', 'Writer results'),
(self.dlm.dl_worker_queue, self.dlm.writer_queue, self.dlm.dl_result_q, self.dlm.writer_result_q)):
logger.debug(f'Cleaning up queue "{name}"')
try:
while True:
_ = q.get_nowait()
except Empty:
q.close()
q.join_thread()
except AttributeError:
logger.warning(f'Queue {name} did not close')
if self.dlm.writer_queue:
# cancel installation
self.dlm.writer_queue.put_nowait(WriterTask('', kill=True))
# forcibly kill DL workers that are not actually dead yet
for child in self.dlm.children:
if child.exitcode is None:
child.terminate()
if self.dlm.shared_memory:
# close up shared memory
self.dlm.shared_memory.close()
self.dlm.shared_memory.unlink()
self.dlm.shared_memory = None
self.dlm.kill()
# force kill any threads that are somehow still alive
for proc in psutil.process_iter():
# check whether the process name matches
if sys.platform in ['linux', 'darwin'] and proc.name() == 'DownloadThread':
proc.kill()
elif sys.platform == 'win32' and proc.name() == 'python.exe' and proc.create_time() >= start_time:
proc.kill()
logger.info("Download stopped. It can be continued later.")
dl_stopped = True
try: try:
self.statistics.emit(self.status_queue.get(timeout=1)) if not dl_stopped:
self.statistics.emit(self.status_queue.get(timeout=1))
except queue.Empty: except queue.Empty:
pass pass
self.dlm.join() self.dlm.join()
except KillDownloadException:
self.status.emit("stop")
logger.info("Downlaod can be continued later")
self.dlm.kill()
return
except Exception as e: except Exception as e:
logger.error(f"Installation failed after {time.time() - start_time:.02f} seconds: {e}") logger.error(f"Installation failed after {time.time() - start_time:.02f} seconds: {e}")
self.status.emit("error") self.status.emit("error "+str(e))
return return
else: else:
if dl_stopped:
return
self.status.emit("dl_finished") self.status.emit("dl_finished")
end_t = time.time() end_t = time.time()
@ -115,3 +170,6 @@ class DownloadThread(QThread):
else: else:
logger.info('Automatic installation not available on Linux.') logger.info('Automatic installation not available on Linux.')
def kill(self):
self._kill = True

View file

@ -64,8 +64,14 @@ class RareSettings(QScrollArea):
self.cloud_sync.setChecked(self.settings.value("auto_sync_cloud", True, bool)) self.cloud_sync.setChecked(self.settings.value("auto_sync_cloud", True, bool))
self.cloud_sync_widget = SettingsWidget(self.tr("Auto sync with cloud"), self.cloud_sync) self.cloud_sync_widget = SettingsWidget(self.tr("Auto sync with cloud"), self.cloud_sync)
self.layout.addWidget(self.cloud_sync_widget) self.layout.addWidget(self.cloud_sync_widget)
self.cloud_sync.stateChanged.connect(lambda: self.settings.setValue(f"auto_sync_cloud", self.cloud_sync.stateChanged.connect(
self.cloud_sync.isChecked())) lambda: self.settings.setValue(f"auto_sync_cloud", self.cloud_sync.isChecked()))
self.save_size = QCheckBox(self.tr("Save size"))
self.save_size.setChecked(self.settings.value("save_size", False, bool))
self.save_size_widget = SettingsWidget(self.tr("Save size of window after restart"), self.save_size)
self.layout.addWidget(self.save_size_widget)
self.save_size.stateChanged.connect(self.save_window_size)
self.save_size = QCheckBox(self.tr("Save size")) self.save_size = QCheckBox(self.tr("Save size"))
self.save_size.setChecked(self.settings.value("save_size", False, bool)) self.save_size.setChecked(self.settings.value("save_size", False, bool))

View file

@ -1,12 +1,12 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction
from qtawesome import icon from rare import style_path
class TrayIcon(QSystemTrayIcon): class TrayIcon(QSystemTrayIcon):
def __init__(self, parent): def __init__(self, parent):
super(TrayIcon, self).__init__(parent) super(TrayIcon, self).__init__(parent)
self.setIcon(icon("ei.cogs", color="white")) # TODO change icon to logo self.setIcon(QIcon(style_path+"Logo.png"))
self.setVisible(True) self.setVisible(True)
self.setToolTip("Rare") self.setToolTip("Rare")

Binary file not shown.

BIN
rare/styles/Logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -13,6 +13,3 @@ class InstallOptions:
self.ignore_free_space = ignore_free_space self.ignore_free_space = ignore_free_space
self.force = force self.force = force
class KillDownloadException(Exception):
pass

View file

@ -3,3 +3,4 @@ Pillow
PyQt5 PyQt5
QtAwesome QtAwesome
notify-py notify-py
psutil

View file

@ -10,6 +10,7 @@ setuptools.setup(
version=version, version=version,
author="Dummerle", author="Dummerle",
license="GPL-3", license="GPL-3",
description="A gui for Legendary",
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
include_package_data=True, include_package_data=True,
@ -32,5 +33,6 @@ setuptools.setup(
"PyQt5", "PyQt5",
"QtAwesome", "QtAwesome",
"notify-py", "notify-py",
"psutil"
], ],
) )