Fix threading. Yeah. I've *fixed* threading.
This commit is contained in:
30
__main__.py
30
__main__.py
@@ -53,7 +53,6 @@
|
|||||||
? Include icons for emblems
|
? Include icons for emblems
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||||
@@ -266,7 +265,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
tab_metadata = self.tabWidget.widget(tab_index).metadata
|
tab_metadata = self.tabWidget.widget(tab_index).metadata
|
||||||
|
|
||||||
self.thread = BackGroundTabUpdate(
|
self.thread = BackGroundTabUpdate(
|
||||||
self.database_path, tab_metadata)
|
self.database_path, [tab_metadata])
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
self.tabWidget.removeTab(tab_index)
|
self.tabWidget.removeTab(tab_index)
|
||||||
@@ -331,7 +330,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
|
|
||||||
path = metadata['path']
|
path = metadata['path']
|
||||||
contents = sorter.BookSorter(
|
contents = sorter.BookSorter(
|
||||||
[path], 'reading', self.database_path).initiate_threads()
|
[path], 'reading', self.database_path, self.temp_dir.path()).initiate_threads()
|
||||||
|
|
||||||
tab_ref = Tab(contents, self.tabWidget)
|
tab_ref = Tab(contents, self.tabWidget)
|
||||||
self.tabWidget.setCurrentWidget(tab_ref)
|
self.tabWidget.setCurrentWidget(tab_ref)
|
||||||
@@ -440,17 +439,24 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
font, font_size, foreground, background))
|
font, font_size, foreground, background))
|
||||||
|
|
||||||
def closeEvent(self, event=None):
|
def closeEvent(self, event=None):
|
||||||
|
|
||||||
# All tabs must be iterated upon here
|
# All tabs must be iterated upon here
|
||||||
for i in range(1, self.tabWidget.count()):
|
self.temp_dir.remove()
|
||||||
tab_metadata = self.tabWidget.widget(i).metadata
|
self.hide()
|
||||||
self.thread = BackGroundTabUpdate(
|
|
||||||
self.database_path, tab_metadata)
|
|
||||||
self.thread.start()
|
|
||||||
self.thread.finished.connect(QtWidgets.qApp.exit)
|
|
||||||
|
|
||||||
Settings(self).save_settings()
|
if self.tabWidget.count() > 1:
|
||||||
QtWidgets.qApp.exit()
|
all_metadata = []
|
||||||
|
|
||||||
|
for i in range(1, self.tabWidget.count()):
|
||||||
|
tab_metadata = self.tabWidget.widget(i).metadata
|
||||||
|
all_metadata.append(tab_metadata)
|
||||||
|
|
||||||
|
self.thread = BackGroundTabUpdate(self.database_path, all_metadata)
|
||||||
|
self.thread.finished.connect(QtWidgets.qApp.exit)
|
||||||
|
self.thread.start()
|
||||||
|
|
||||||
|
else:
|
||||||
|
Settings(self).save_settings()
|
||||||
|
QtWidgets.qApp.exit()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
13
database.py
13
database.py
@@ -115,11 +115,16 @@ class DatabaseFunctions:
|
|||||||
|
|
||||||
self.close_database()
|
self.close_database()
|
||||||
|
|
||||||
def modify_position(self, file_hash, position):
|
def modify_position(self, hash_position_pairs):
|
||||||
pickled_position = pickle.dumps(position)
|
for i in hash_position_pairs:
|
||||||
|
file_hash = i[0]
|
||||||
|
position = i[1]
|
||||||
|
|
||||||
|
pickled_position = pickle.dumps(position)
|
||||||
|
|
||||||
|
sql_command = "UPDATE books SET Position = ? WHERE Hash = ?"
|
||||||
|
self.database.execute(sql_command, [sqlite3.Binary(pickled_position), file_hash])
|
||||||
|
|
||||||
sql_command = "UPDATE books SET Position = ? WHERE Hash = ?"
|
|
||||||
self.database.execute(sql_command, [sqlite3.Binary(pickled_position), file_hash])
|
|
||||||
self.database.commit()
|
self.database.commit()
|
||||||
self.close_database()
|
self.close_database()
|
||||||
|
|
||||||
|
@@ -3,16 +3,17 @@
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import zipfile
|
import zipfile
|
||||||
import tempfile
|
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
|
||||||
class ParseCBZ:
|
class ParseCBZ:
|
||||||
def __init__(self, filename):
|
def __init__(self, filename, temp_dir, file_md5):
|
||||||
# TODO
|
# TODO
|
||||||
# Maybe also include book description
|
# Maybe also include book description
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.book = None
|
self.book = None
|
||||||
|
self.temp_dir = temp_dir
|
||||||
|
self.file_md5 = file_md5
|
||||||
|
|
||||||
def read_book(self):
|
def read_book(self):
|
||||||
try:
|
try:
|
||||||
@@ -43,17 +44,17 @@ class ParseCBZ:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def get_contents(self):
|
def get_contents(self):
|
||||||
|
extract_path = os.path.join(self.temp_dir, self.file_md5)
|
||||||
contents = collections.OrderedDict()
|
contents = collections.OrderedDict()
|
||||||
# This is a brute force approach
|
# This is a brute force approach
|
||||||
# Maybe try reading from the file as everything
|
# Maybe try reading from the file as everything
|
||||||
# matures a little bit more
|
# matures a little bit more
|
||||||
temp_dir = tempfile.mkdtemp()
|
|
||||||
|
|
||||||
contents = collections.OrderedDict()
|
contents = collections.OrderedDict()
|
||||||
for count, i in enumerate(self.book.infolist()):
|
for count, i in enumerate(self.book.infolist()):
|
||||||
self.book.extract(i, path=temp_dir)
|
self.book.extract(i, path=extract_path)
|
||||||
page_name = 'Page ' + str(count + 1)
|
page_name = 'Page ' + str(count + 1)
|
||||||
image_path = os.path.join(temp_dir, i.filename)
|
image_path = os.path.join(extract_path, i.filename)
|
||||||
# This does image returns.
|
# This does image returns.
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
@@ -64,7 +65,7 @@ class ParseCBZ:
|
|||||||
contents[page_name] = "<img src='%s' align='middle'/>" % image_path
|
contents[page_name] = "<img src='%s' align='middle'/>" % image_path
|
||||||
|
|
||||||
file_settings = {
|
file_settings = {
|
||||||
'temp_dir': temp_dir,
|
'temp_dir': self.temp_dir,
|
||||||
'images_only': True}
|
'images_only': True}
|
||||||
|
|
||||||
return contents, file_settings
|
return contents, file_settings
|
||||||
|
@@ -10,17 +10,20 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import zipfile
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
import ebooklib.epub
|
import ebooklib.epub
|
||||||
|
|
||||||
|
|
||||||
class ParseEPUB:
|
class ParseEPUB:
|
||||||
def __init__(self, filename):
|
def __init__(self, filename, temp_dir, file_md5):
|
||||||
# TODO
|
# TODO
|
||||||
# Maybe also include book description
|
# Maybe also include book description
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.book = None
|
self.book = None
|
||||||
|
self.temp_dir = temp_dir
|
||||||
|
self.file_md5 = file_md5
|
||||||
|
|
||||||
def read_book(self):
|
def read_book(self):
|
||||||
try:
|
try:
|
||||||
@@ -103,6 +106,11 @@ class ParseEPUB:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def get_contents(self):
|
def get_contents(self):
|
||||||
|
# Extract all contents to a temporary directory
|
||||||
|
# for relative path lookup voodoo
|
||||||
|
extract_path = os.path.join(self.temp_dir, self.file_md5)
|
||||||
|
zipfile.ZipFile(self.filename).extractall(extract_path)
|
||||||
|
|
||||||
contents = collections.OrderedDict()
|
contents = collections.OrderedDict()
|
||||||
|
|
||||||
def flatten_chapter(toc_element):
|
def flatten_chapter(toc_element):
|
||||||
@@ -141,7 +149,7 @@ class ParseEPUB:
|
|||||||
# Special settings that have to be returned with the file
|
# Special settings that have to be returned with the file
|
||||||
# Referenced in sorter.py
|
# Referenced in sorter.py
|
||||||
file_settings = {
|
file_settings = {
|
||||||
'temp_dir': None,
|
'temp_dir': extract_path,
|
||||||
'images_only': False}
|
'images_only': False}
|
||||||
|
|
||||||
return contents, file_settings
|
return contents, file_settings
|
||||||
|
13
sorter.py
13
sorter.py
@@ -25,7 +25,7 @@ from parsers.cbz import ParseCBZ
|
|||||||
|
|
||||||
|
|
||||||
class BookSorter:
|
class BookSorter:
|
||||||
def __init__(self, file_list, mode, database_path):
|
def __init__(self, file_list, mode, database_path, temp_dir=None):
|
||||||
# Have the GUI pass a list of files straight to here
|
# Have the GUI pass a list of files straight to here
|
||||||
# Then, on the basis of what is needed, pass the
|
# Then, on the basis of what is needed, pass the
|
||||||
# filenames to the requisite functions
|
# filenames to the requisite functions
|
||||||
@@ -35,10 +35,11 @@ class BookSorter:
|
|||||||
self.file_list = file_list
|
self.file_list = file_list
|
||||||
self.statistics = [0, (len(file_list))]
|
self.statistics = [0, (len(file_list))]
|
||||||
self.all_books = {}
|
self.all_books = {}
|
||||||
self.database_path = database_path
|
|
||||||
self.hashes = []
|
self.hashes = []
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
if database_path:
|
self.database_path = database_path
|
||||||
|
self.temp_dir = temp_dir
|
||||||
|
if database_path and self.mode == 'reading':
|
||||||
self.database_hashes()
|
self.database_hashes()
|
||||||
|
|
||||||
def database_hashes(self):
|
def database_hashes(self):
|
||||||
@@ -87,13 +88,13 @@ class BookSorter:
|
|||||||
and (file_md5 in self.all_books.items() or file_md5 in self.hashes)):
|
and (file_md5 in self.all_books.items() or file_md5 in self.hashes)):
|
||||||
return
|
return
|
||||||
|
|
||||||
# SORTING TAKES PLACE HERE
|
# ___________SORTING TAKES PLACE HERE___________
|
||||||
try:
|
try:
|
||||||
file_extension = os.path.splitext(filename)[1][1:]
|
file_extension = os.path.splitext(filename)[1][1:]
|
||||||
if file_extension == 'epub':
|
if file_extension == 'epub':
|
||||||
book_ref = ParseEPUB(filename)
|
book_ref = ParseEPUB(filename, self.temp_dir, file_md5)
|
||||||
if file_extension == 'cbz':
|
if file_extension == 'cbz':
|
||||||
book_ref = ParseCBZ(filename)
|
book_ref = ParseCBZ(filename, self.temp_dir, file_md5)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
20
widgets.py
20
widgets.py
@@ -284,6 +284,7 @@ class Tab(QtWidgets.QWidget):
|
|||||||
|
|
||||||
title = self.metadata['title']
|
title = self.metadata['title']
|
||||||
position = self.metadata['position']
|
position = self.metadata['position']
|
||||||
|
relative_path_root = self.metadata['temp_dir']
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
# Chapter position and vertical scrollbar position
|
# Chapter position and vertical scrollbar position
|
||||||
@@ -295,6 +296,7 @@ class Tab(QtWidgets.QWidget):
|
|||||||
|
|
||||||
chapter_name = list(self.metadata['content'])[current_chapter - 1]
|
chapter_name = list(self.metadata['content'])[current_chapter - 1]
|
||||||
chapter_content = self.metadata['content'][chapter_name]
|
chapter_content = self.metadata['content'][chapter_name]
|
||||||
|
self.contentView.setSearchPaths([relative_path_root])
|
||||||
self.contentView.setHtml(chapter_content)
|
self.contentView.setHtml(chapter_content)
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.contentView, 0, 0, 1, 1)
|
self.gridLayout.addWidget(self.contentView, 0, 0, 1, 1)
|
||||||
@@ -378,20 +380,20 @@ class MyAbsModel(QtGui.QStandardItemModel, QtCore.QAbstractItemModel):
|
|||||||
|
|
||||||
|
|
||||||
class BackGroundTabUpdate(QtCore.QThread):
|
class BackGroundTabUpdate(QtCore.QThread):
|
||||||
def __init__(self, database_path, tab_metadata, parent=None):
|
def __init__(self, database_path, all_metadata, parent=None):
|
||||||
super(BackGroundTabUpdate, self).__init__(parent)
|
super(BackGroundTabUpdate, self).__init__(parent)
|
||||||
self.database_path = database_path
|
self.database_path = database_path
|
||||||
self.tab_metadata = tab_metadata
|
self.all_metadata = all_metadata
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
file_hash = self.tab_metadata['hash']
|
hash_position_pairs = []
|
||||||
position = self.tab_metadata['position']
|
for i in self.all_metadata:
|
||||||
database.DatabaseFunctions(
|
file_hash = i['hash']
|
||||||
self.database_path).modify_position(file_hash, position)
|
position = i['position']
|
||||||
|
hash_position_pairs.append([file_hash, position])
|
||||||
|
|
||||||
temp_dir = self.tab_metadata['temp_dir']
|
database.DatabaseFunctions(
|
||||||
if temp_dir:
|
self.database_path).modify_position(hash_position_pairs)
|
||||||
shutil.rmtree(temp_dir)
|
|
||||||
|
|
||||||
|
|
||||||
class BackGroundBookAddition(QtCore.QThread):
|
class BackGroundBookAddition(QtCore.QThread):
|
||||||
|
Reference in New Issue
Block a user