Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
10839623c6
2
.github/GenPKG.sh
vendored
2
.github/GenPKG.sh
vendored
|
@ -1,5 +1,5 @@
|
|||
export PYTHONPATH=$PWD
|
||||
version=$(python3 Rare --version)
|
||||
version=$(python3 rare --version)
|
||||
cd .github
|
||||
git clone https://aur.archlinux.org/rare.git
|
||||
cd ..
|
||||
|
|
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
|
@ -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
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
pypy-deploy:
|
||||
|
@ -61,9 +58,10 @@ jobs:
|
|||
pip3 install pyinstaller setuptools wheel
|
||||
pip3 install -r requirements.txt
|
||||
- name: Prepare
|
||||
run: cp Rare/__main__.py ./
|
||||
run: cp rare/__main__.py ./
|
||||
- name: Build
|
||||
run: pyinstaller
|
||||
--icon=rare/styles/Logo.ico
|
||||
--onefile
|
||||
--name Rare
|
||||
--add-data="Rare/languages/*;Rare/languages"
|
||||
|
@ -91,7 +89,7 @@ jobs:
|
|||
python3-requests
|
||||
python3-pyqt5
|
||||
python3-pil
|
||||
python3-qtawesome-common
|
||||
python3-qtawesome
|
||||
python3-setuptools
|
||||
python3-wheel
|
||||
|
||||
|
@ -101,7 +99,7 @@ jobs:
|
|||
python3 setup.py --command-packages=stdeb.command bdist_deb
|
||||
|
||||
- name: move file
|
||||
run: mv deb_dist/*.deb rare.deb
|
||||
run: mv deb_dist/*.deb Rare.deb
|
||||
|
||||
- name: Upload files to GitHub
|
||||
uses: svenstaro/upload-release-action@2.2.1
|
||||
|
|
|
@ -19,7 +19,8 @@ exmples:
|
|||
Select one Card of the project and implement it or make other changes
|
||||
|
||||
|
||||
##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.
|
||||
## Git crash-course
|
||||
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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
include README.md
|
||||
include rare/languages/de.qm
|
||||
include rare/languages/*.qm
|
||||
include rare/styles/*
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
|
||||
__version__ = "1.0_beta2"
|
||||
__version__ = "1.0.0"
|
||||
style_path = os.path.join(os.path.dirname(__file__), "styles/")
|
||||
lang_path = os.path.join(os.path.dirname(__file__), "languages/")
|
||||
|
|
|
@ -50,9 +50,9 @@ class DownloadTab(QWidget):
|
|||
self.mini_layout.addWidget(self.prog_bar)
|
||||
|
||||
self.kill_button = QPushButton(self.tr("Stop Download"))
|
||||
# self.mini_layout.addWidget(self.kill_button)
|
||||
self.kill_button.setDisabled(True)
|
||||
self.kill_button.clicked.connect(self.stop_download)
|
||||
self.mini_layout.addWidget(self.kill_button)
|
||||
|
||||
self.layout.addLayout(self.mini_layout)
|
||||
|
||||
|
@ -85,7 +85,7 @@ class DownloadTab(QWidget):
|
|||
self.dl_queue = dl_queue
|
||||
|
||||
def stop_download(self):
|
||||
self.thread.kill = True
|
||||
self.thread.kill()
|
||||
|
||||
def install_game(self, options: InstallOptions):
|
||||
|
||||
|
@ -227,11 +227,12 @@ class DownloadTab(QWidget):
|
|||
else:
|
||||
self.queue_widget.update_queue(self.dl_queue)
|
||||
|
||||
elif text == "error":
|
||||
QMessageBox.warning(self, "warn", "Download error")
|
||||
elif text[:5] == "error":
|
||||
QMessageBox.warning(self, "warn", "Download error: "+text[6:])
|
||||
|
||||
elif text == "stop":
|
||||
self.reset_infos()
|
||||
self.active_game = None
|
||||
|
||||
def reset_infos(self):
|
||||
self.kill_button.setDisabled(True)
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import os
|
||||
import queue
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from logging import getLogger
|
||||
from multiprocessing import Queue as MPQueue
|
||||
from queue import Empty
|
||||
|
||||
import psutil
|
||||
from PyQt5.QtCore import QThread, pyqtSignal
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
from rare.utils.models import KillDownloadException
|
||||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
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")
|
||||
|
||||
|
@ -20,7 +21,6 @@ logger = getLogger("Download")
|
|||
class DownloadThread(QThread):
|
||||
status = pyqtSignal(str)
|
||||
statistics = pyqtSignal(UIUpdate)
|
||||
kill = False
|
||||
|
||||
def __init__(self, dlm: DLManager, core: LegendaryCore, status_queue: MPQueue, igame, repair=False,
|
||||
repair_file=None):
|
||||
|
@ -31,37 +31,92 @@ class DownloadThread(QThread):
|
|||
self.igame = igame
|
||||
self.repair = repair
|
||||
self.repair_file = repair_file
|
||||
self._kill = False
|
||||
|
||||
def run(self):
|
||||
start_time = time.time()
|
||||
dl_stopped = False
|
||||
try:
|
||||
|
||||
self.dlm.start()
|
||||
time.sleep(1)
|
||||
while self.dlm.is_alive():
|
||||
if self.kill:
|
||||
# raise KillDownloadException()
|
||||
# TODO kill download queue, workers
|
||||
pass
|
||||
if self._kill:
|
||||
self.status.emit("stop")
|
||||
logger.info("Download stopping...")
|
||||
|
||||
# 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:
|
||||
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:
|
||||
pass
|
||||
|
||||
self.dlm.join()
|
||||
|
||||
except KillDownloadException:
|
||||
self.status.emit("stop")
|
||||
logger.info("Downlaod can be continued later")
|
||||
self.dlm.kill()
|
||||
return
|
||||
|
||||
except Exception as 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
|
||||
|
||||
else:
|
||||
if dl_stopped:
|
||||
return
|
||||
self.status.emit("dl_finished")
|
||||
end_t = time.time()
|
||||
|
||||
|
@ -115,3 +170,6 @@ class DownloadThread(QThread):
|
|||
else:
|
||||
logger.info('Automatic installation not available on Linux.')
|
||||
|
||||
def kill(self):
|
||||
self._kill = True
|
||||
|
||||
|
|
|
@ -64,8 +64,14 @@ class RareSettings(QScrollArea):
|
|||
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.layout.addWidget(self.cloud_sync_widget)
|
||||
self.cloud_sync.stateChanged.connect(lambda: self.settings.setValue(f"auto_sync_cloud",
|
||||
self.cloud_sync.isChecked()))
|
||||
self.cloud_sync.stateChanged.connect(
|
||||
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.setChecked(self.settings.value("save_size", False, bool))
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from PyQt5.QtCore import QCoreApplication
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction
|
||||
from qtawesome import icon
|
||||
from rare import style_path
|
||||
|
||||
|
||||
class TrayIcon(QSystemTrayIcon):
|
||||
def __init__(self, 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.setToolTip("Rare")
|
||||
|
||||
|
|
Binary file not shown.
BIN
rare/styles/Logo.ico
Normal file
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 |
|
@ -13,6 +13,3 @@ class InstallOptions:
|
|||
self.ignore_free_space = ignore_free_space
|
||||
self.force = force
|
||||
|
||||
|
||||
class KillDownloadException(Exception):
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ Pillow
|
|||
PyQt5
|
||||
QtAwesome
|
||||
notify-py
|
||||
psutil
|
||||
|
|
2
setup.py
2
setup.py
|
@ -10,6 +10,7 @@ setuptools.setup(
|
|||
version=version,
|
||||
author="Dummerle",
|
||||
license="GPL-3",
|
||||
description="A gui for Legendary",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
include_package_data=True,
|
||||
|
@ -32,5 +33,6 @@ setuptools.setup(
|
|||
"PyQt5",
|
||||
"QtAwesome",
|
||||
"notify-py",
|
||||
"psutil"
|
||||
],
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue