Skip to content

Commit

Permalink
MV 1.4r release
Browse files Browse the repository at this point in the history
  • Loading branch information
adalfarus committed May 25, 2024
1 parent 4907687 commit c765cfa
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 55 deletions.
Binary file modified data/data.db
Binary file not shown.
2 changes: 1 addition & 1 deletion extensionss/ManhwaFilePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def _convert_image_format(self, source_path, new_name=None, target_format='png')
def _empty_cache(self):
files = os.listdir(self.cache_folder)
for f in files:
os.remove(f"{self.cache_folder}/{f}")
os.remove(f"{self.cache_folder}{f}")
#list( map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) ) )

def _make_cache_readable(self):
Expand Down
6 changes: 3 additions & 3 deletions installer_script_1.3.iss → installer_script_1.4.iss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "ManhwaViewer"
#define MyAppVersion "1.3"
#define MyAppVersion "1.4"
#define MyAppPublisher "Cariel Becker"
#define MyAppURL "https://www.cariel-becker.com/"
#define MyAppExeName "manhwaviewer.exe"
Expand All @@ -13,7 +13,7 @@
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{D17631D2-5D1E-4AB4-9144-2616F3ACADDC}
AppId={{AE89B46C-6E4F-4B1D-BB7E-E697B5BA06A7}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
Expand All @@ -30,7 +30,7 @@ DisableProgramGroupPage=yes
PrivilegesRequired=lowest
;PrivilegesRequiredOverridesAllowed=dialog
OutputDir=.\
OutputBaseFilename=manhwaviewer-v1.3-win10-11-x64-installer
OutputBaseFilename=manhwaviewer-v1.4-win10-11-x64-installer
SetupIconFile=.\data\logo2.ico
Compression=lzma
SolidCompression=yes
Expand Down
198 changes: 153 additions & 45 deletions manhwaviewer.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
from logging import raiseExceptions
from traceback import print_tb
from PySide6.QtWidgets import (QApplication, QLabel, QVBoxLayout, QScrollArea,
QWidget, QMainWindow, QCheckBox, QHBoxLayout,
QSpinBox, QPushButton, QGraphicsOpacityEffect,
QFrame, QComboBox, QFormLayout, QSlider, QLineEdit,
QRadioButton, QDialog, QGroupBox, QToolButton,
QDialogButtonBox, QMessageBox, QFileDialog,
QProgressDialog, )
QProgressDialog)
from PySide6.QtGui import QPixmap, QPalette, QColor, QIcon, QDoubleValidator
from PySide6.QtCore import Qt, QTimer, QPropertyAnimation, QRect, QThread, Signal
from PySide6.QtCore import Qt, QTimer, QPropertyAnimation, QRect, QThread, Signal, Slot
from extensions.ManhwaFilePlugin import ManhwaFilePlugin
from extensions.AutoProviderPlugin import AutoProviderPlugin
from extensions.extra_autoprovider_plugins import *
from pathlib import Path
import importlib.util
#import threading
import threading # Implement, needed if website is very slow
import base64
import ctypes # Implement, needed if website is very slow
import json
import time
import sys
Expand Down Expand Up @@ -439,39 +441,124 @@ def accept(self):
self.file, self.chapter]
super().accept()

class Loader(QThread):
progress = Signal(int)
loading_complete = Signal()
class TaskRunner(QThread):
task_completed = Signal(bool, object)

def __init__(self, parent=None):
super().__init__(parent)
self.complete = False
def __init__(self, func, *args, **kwargs):
super().__init__()
self.func = func
self.args = args
self.kwargs = kwargs
self.is_running = True
self.worker_thread = None
self.result = None
self.success = False

self.progressDialog = QProgressDialog("Loading...", None, 0, 100, parent)
self.progressDialog.setCancelButton(None)
self.progress.connect(self.updateProgress)
self.loading_complete.connect(self.progressDialog.close)
class TaskCanceledException(Exception):
"""Exception to be raised when the task is canceled"""
def __init__(self, message="A intended error occured"):
self.message = message
super().__init__(self.message)

def run(self):
print("running")
self.progressDialog.show()
print("showed")
if not self.is_running:
return

try:
self.worker_thread = threading.Thread(target=self.worker_func)
self.worker_thread.start()
self.worker_thread.join()
self.task_completed.emit(self.success, self.result)

except Exception as e:
self.task_completed.emit(False, None)
print(e)

def worker_func(self):
try:
self.result = self.func(*self.args, **self.kwargs)
self.success = True
except SystemExit:
self.success = False
self.result = None
print("Task was forcefully stopped.")
except Exception as e:
self.success = False
self.result = None
print(e)

def stop(self):
print("Task is stopping.")
self.is_running = False
if not self.isFinished():
self.raise_exception()
self.wait()

def get_thread_id(self):
if self.worker_thread:
return self.worker_thread.ident

def raise_exception(self):
thread_id = self.get_thread_id()
if thread_id:
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), ctypes.py_object(SystemExit))
if res > 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
print("Exception raise failure")

class CustomProgressDialog(QProgressDialog):

def __init__(self, windowTitle, windowIcon, windowLable="Doing a task...", buttonText="Cancel", func=lambda: None, *args, **kwargs):
super().__init__(windowLable, buttonText, 0, 100)
self.setWindowTitle(windowTitle)
self.setWindowIcon(QIcon(windowIcon))

self.taskRunner = TaskRunner(func, *args, **kwargs)
self.taskRunner.task_completed.connect(self.onTaskCompleted)
self.task_successful = False

self.setAutoClose(False)
self.setAutoReset(False)
self.setWindowModality(Qt.ApplicationModal)
self.canceled.connect(self.cancelTask)
self.show()

for i in range(99):
print("doing stuff")
if self.complete:
self.progress.emit(100)
break
self.progress.emit(i)
QThread.sleep(1) # Adjust the sleep time as necessary
self.taskRunner.start()

self.loading_complete.emit()
while self.value() < 99 and not self.wasCanceled() and self.taskRunner.isRunning():
self.setValue(self.value() + 1)
time.sleep(0.1)
QApplication.processEvents()

def updateProgress(self, value):
self.progressDialog.setValue(value)
@Slot(bool, object)
def onTaskCompleted(self, success, result):
self.taskRunner.quit()
self.taskRunner.wait()

def completeLoading(self):
self.complete = True
if not self.wasCanceled():
if success:
self.task_successful = True
self.setValue(100)
print("Task completed successfully! Result:" + str(result)) # Adjust as needed
QTimer.singleShot(1000, self.accept) # Close after 1 second if successful
else:
palette = QPalette(self.palette())
palette.setColor(QPalette.Highlight, QColor(Qt.red))
self.setPalette(palette)
self.setLabelText("Task failed!")
self.setCancelButtonText("Close")

def cancelTask(self):
self.taskRunner.stop()
self.taskRunner.wait()
self.setValue(0)
self.setLabelText("Task cancelled")
self.close()

def closeEvent(self, event):
if self.taskRunner.isRunning():
self.cancelTask()
event.accept()

def absolute_path(relative_path):
ab = os.path.dirname(__file__)
Expand All @@ -487,7 +574,7 @@ def __init__(self, parent=None):

self.setupUi()

self.setWindowTitle('Manhwa Viewer 1.5')
self.setWindowTitle('Manhwa Viewer 1.2')
self.setWindowIcon(QIcon(f'{self.data_folder}logo2.png'))

db_path = Path(f"{self.data_folder}data.db")
Expand All @@ -512,6 +599,7 @@ def __init__(self, parent=None):
self.logo_path = self.prov.get_logo_path()
self.prov.set_blacklisted_websites(self.settings.get_blacklisted_websites())
print(self.prov)
self.setWindowTitle(f'MV 1.2 | {self.prov.get_title().title()}, Chapter {self.prov.get_chapter()}')

self.current_width = 0
self.manual_width = self.settings.get_manual_width()
Expand All @@ -520,6 +608,8 @@ def __init__(self, parent=None):
self.prev_downscale_state = self.settings.get_downscaling()
self.prev_upscale_state = self.settings.get_upscaling()
self.image_paths = self.get_image_paths()
self.task_successful = False
self.threading = False

# Image Labels
self.image_labels = []
Expand Down Expand Up @@ -856,6 +946,7 @@ def set_file_path(self):
def closeEvent(self, event):
can_exit = True
if can_exit:
print("Exiting ...")
if self.settings.get_provider() == "auto":
self.settings.set_autoprovider(self.provider_dropdown.currentText())
elif self.settings.get_provider() == "file":
Expand All @@ -875,6 +966,7 @@ def closeEvent(self, event):
self.prov.redo_prep()
event.accept() # let the window close
else:
print("Couldn't exit.")
event.ignore()

def onRadioBtnToggled(self):
Expand Down Expand Up @@ -1116,18 +1208,18 @@ def reload_images(self):
print("Images reloaded")

def next_chapter(self):
self.loader = Loader(self)
print("init loader")
self.loader.start()
print("started loader")
value = self.prov.next_chapter()
print("finished task")
self.loader.complete_loading()
print("finished loader")

if value:
self.threading = True
self.progressDialog = CustomProgressDialog(windowTitle="Loading ...", windowIcon=f"{self.data_folder}logo2.png", func=self.prov.next_chapter)
self.progressDialog.exec_()

self.task_successful = self.progressDialog.task_successful
self.threading = False

if self.task_successful:
self.setWindowTitle(f'MV 1.2 | {self.prov.get_title().title()}, Chapter {self.prov.get_chapter()}')
self.settings.set_chapter(self.prov.get_chapter())
if self.settings.get_auto_export() and self.settings.get_provider() == "auto": self.export_chapter()
self.task_successful = False
else:
self.prov.set_chapter(self.settings.get_chapter())
self.prov.reload_chapter()
Expand All @@ -1141,10 +1233,18 @@ def next_chapter(self):
self.reload_images()

def previous_chapter(self):
value = self.prov.previous_chapter()
if value:
self.threading = True
self.progressDialog = CustomProgressDialog(windowTitle="Loading ...", windowIcon=f"{self.data_folder}logo2.png", func=self.prov.previous_chapter)
self.progressDialog.exec_()

self.task_successful = self.progressDialog.task_successful
self.threading = False

if self.task_successful:
self.setWindowTitle(f'MV 1.2 | {self.prov.get_title().title()}, Chapter {self.prov.get_chapter()}')
self.settings.set_chapter(self.prov.get_chapter())
if self.settings.get_auto_export() and self.settings.get_provider() == "auto": self.export_chapter()
self.task_successful = False
else:
self.prov.set_chapter(self.settings.get_chapter())
self.prov.reload_chapter()
Expand All @@ -1158,10 +1258,18 @@ def previous_chapter(self):
self.reload_images()

def reload_chapter(self):
value = self.prov.reload_chapter()
if value:
self.threading = True
self.progressDialog = CustomProgressDialog(windowTitle="Loading ...", windowIcon=f"{self.data_folder}logo2.png", func=self.prov.reload_chapter)
self.progressDialog.exec_()

self.task_successful = self.progressDialog.task_successful
self.threading = False

if self.task_successful:
self.setWindowTitle(f'MV 1.2 | {self.prov.get_title().title()}, Chapter {self.prov.get_chapter()}')
self.settings.set_chapter(self.prov.get_chapter())
if self.settings.get_auto_export() and self.settings.get_provider() == "auto": self.export_chapter() # Keep?
self.task_successful = False
else:
self.prov.set_chapter(self.settings.get_chapter())
self.prov.reload_chapter()
Expand All @@ -1173,9 +1281,9 @@ def reload_chapter(self):
print("Reloading images...")
self.scroll_area.verticalScrollBar().setValue(0) # Reset the scrollbar position to the top
self.reload_images()

def timer_tick(self):
self.update_images()
if not self.threading: self.update_images()
#print("Update tick") # Debug

if __name__ == "__main__":
Expand Down
13 changes: 7 additions & 6 deletions needed_fixes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
- fix overlaying of images on to side menu, when reloading (next chapter, etc.) # Fixed
-> Repaint
- popups for events (like failed to load [next] chapter) # Fixed
- better handeling of chapter loading times # Fixed
- title and chapter shown as name next to manhwaviewer # Fixed shown next to MV to make shorter and more readable
- Make CustomProgressDialog look better and more customizable # Fixed

- better handeling of chapter loading times
- better exporting of chapters
- add indirect and direct mode (indirect, what direct is at the moment, direct use the href from website
to go to next chapter, etc. --> direct would require a start manga url [could potentially also extract it from chapter url])
- better speed for loading chapters
-> preloading of the previous and the next chapter
- better exporting of chapters
- adding support for text only and video (plugins)
- add indirect and direct mode (indirect, what direct is at the moment, direct use the href from website
to go to next chapter, etc. --> direct would require a start manga url [could potentially also extract it from chapter url])
- title and chapter shown as name next to manhwaviewer
- add support for anime and comic compilation videos
- add support for anime and comic compilation videos

0 comments on commit c765cfa

Please sign in to comment.