Skip to content

Commit 201e20f

Browse files
committed
the internal ebook reader could nowread .epub file, start of the creation of ebook editor
1 parent 2cf3f44 commit 201e20f

31 files changed

+1341
-125
lines changed

bdd.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sqlite3
88
# sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
99
from common import *
10+
from vars import *
1011

1112

1213
def dict_factory(cursor, row):
@@ -25,7 +26,7 @@ def dict_factory(cursor, row):
2526

2627
class BDD:
2728
def __init__(self):
28-
self.connexion = sqlite3.connect('database.db')
29+
self.connexion = sqlite3.connect(appDir + os.sep + 'database.db')
2930
self.connexion.row_factory = dict_factory
3031
self.cursor = self.connexion.cursor()
3132

booksTools.py

Lines changed: 104 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
import shutil
66
import traceback
77
from xml.dom import minidom
8+
from bs4 import BeautifulSoup
89
import bdd
910
from common import *
11+
from vars import *
1012
import PIL
1113
from PIL import Image
1214
import base64
15+
import zipfile
1316

1417

1518
def create_thumbnail(path: str):
@@ -32,6 +35,100 @@ def create_thumbnail(path: str):
3235
return 'data:image/jpeg;base64,'+base64.b64encode(buffer.getvalue()).decode()
3336

3437

38+
def getEpubIfo(path: str):
39+
ret = {
40+
'guid': None,
41+
'title': None,
42+
'authors': None,
43+
'serie': None,
44+
'tags': None,
45+
'cover': None,
46+
'toc': None,
47+
'chapters': list()
48+
}
49+
try:
50+
if os.path.isfile(path) is True:
51+
myzip = zipfile.ZipFile(path, 'r')
52+
53+
myfile = myzip.open('META-INF/container.xml')
54+
mydoc = minidom.parseString(myfile.read())
55+
item = mydoc.getElementsByTagName('rootfile')[0]
56+
file2 = item.attributes['full-path'].value
57+
myfile.close()
58+
59+
base = ''
60+
if '/' in file2:
61+
tab = file2.split('/')
62+
base = ''
63+
i = 0
64+
while i < len(tab) - 1:
65+
if i > 0: base += '/'
66+
base += tab[i]
67+
i+=1
68+
base += '/'
69+
myfile = myzip.open(file2)
70+
mydoc = minidom.parseString(myfile.read())
71+
72+
try: ret['guid'] = mydoc.getElementsByTagName('dc:identifier')[0].firstChild.data
73+
except Exception: {}
74+
try: ret['title'] = mydoc.getElementsByTagName('dc:title')[0].firstChild.data
75+
except Exception: {}
76+
try: ret['authors'] = mydoc.getElementsByTagName('dc:creator')[0].firstChild.data
77+
except Exception: {}
78+
try: ret['serie'] = mydoc.getElementsByTagName('dc:subject')[0].firstChild.data
79+
except Exception: {}
80+
81+
metas = mydoc.getElementsByTagName('meta')
82+
cov_id = ''
83+
for meta in metas:
84+
if meta.attributes['name'].value == 'cover': cov_id = meta.attributes['content'].value
85+
if meta.attributes['name'].value == 'calibre:series': ret['serie'] = meta.attributes['content'].value
86+
87+
items = mydoc.getElementsByTagName('item')
88+
spine = mydoc.getElementsByTagName('spine')[0].attributes['toc'].value
89+
90+
for itm in items:
91+
if itm.attributes['id'].value == spine:
92+
ret['toc'] = itm.attributes['href'].value
93+
if cov_id != '':
94+
if itm.attributes['id'].value == cov_id:
95+
filepath, ext = os.path.splitext(itm.attributes['href'].value)
96+
tmpdir = appDir + '/tmp' # create var for temporary file extraction
97+
if os.path.isdir(tmpdir) is False:
98+
os.makedirs(tmpdir)
99+
mfile = myzip.extract(base+itm.attributes['href'].value, tmpdir)
100+
ret['cover'] = create_thumbnail(mfile)
101+
break
102+
else:
103+
if itm.attributes['media-type'].value in ['image/jpeg', 'image/png']:
104+
filepath, ext = os.path.splitext(itm.attributes['href'].value)
105+
tmpdir = appDir + '/tmp' # create var for temporary file extraction
106+
if os.path.isdir(tmpdir) is False:
107+
os.makedirs(tmpdir)
108+
mfile = myzip.extract(base+itm.attributes['href'].value, tmpdir)
109+
ret['cover'] = create_thumbnail(mfile)
110+
break
111+
myfile.close()
112+
113+
myfile = myzip.open(base+ret['toc'])
114+
mydoc = minidom.parseString(myfile.read())
115+
itemrefs = mydoc.getElementsByTagName('navPoint')
116+
for ref in itemrefs:
117+
id = ref.attributes['id'].value
118+
ret['chapters'].append({
119+
'id': ref.attributes['id'].value,
120+
'name': ref.getElementsByTagName('text')[0].firstChild.data,
121+
'src': base+ref.getElementsByTagName('content')[0].attributes['src'].value
122+
})
123+
myfile.close()
124+
125+
myzip.close()
126+
return ret
127+
except Exception:
128+
traceback.print_exc()
129+
return None
130+
131+
35132
def insertBook(tools: dict, database: bdd.BDD, file_name_template: str, file_name_separator: str, file: str):
36133
if os.path.isfile(file) is True:
37134
# list of var for future injection into database
@@ -64,49 +161,13 @@ def insertBook(tools: dict, database: bdd.BDD, file_name_template: str, file_nam
64161

65162
if ext in ['.epub', '.epub2', '.epub3']: # section for EPUB files
66163
tmp_guid = uid() # assign random guid for CBZ and CBR books
67-
list_args = list() # create list argument for external command execution
68-
list_args.append(tools['7zip'][os.name]['path']) # insert executable path
69-
temp_args = tools['7zip'][os.name]['params_deflate'].split(' ') # create table of raw command arguments
70-
for var in temp_args: # parse table of raw command arguments
71-
# insert parsed param
72-
list_args.append(var.replace('%input%', file).replace('%output%', tmpdir))
73-
print(list_args)
74-
process = subprocess.Popen(list_args, shell=False) # execute the command
75-
process.wait()
76-
# print(process.returncode)
77-
78-
try:
79-
metainfo_file = tmpdir + '/META-INF/container.xml'
80-
mydoc = minidom.parse(metainfo_file)
81-
item = mydoc.getElementsByTagName('rootfile')[0]
82-
print( item.attributes['full-path'].value )
83-
84-
metadata_file = tmpdir + '/' + item.attributes['full-path'].value
85-
mydoc = minidom.parse(metadata_file)
86-
try: tmp_guid = mydoc.getElementsByTagName('dc:identifier')[0].firstChild.data
87-
except Exception: {}
88-
try: tmp_title = mydoc.getElementsByTagName('dc:title')[0].firstChild.data
89-
except Exception: {}
90-
try: tmp_authors = mydoc.getElementsByTagName('dc:creator')[0].firstChild.data
91-
except Exception: {}
92-
try: tmp_serie = mydoc.getElementsByTagName('dc:subject')[0].firstChild.data
93-
except Exception: {}
94-
metas = mydoc.getElementsByTagName('meta')
95-
cov_id = ''
96-
for meta in metas:
97-
if meta.attributes['name'].value == 'cover':
98-
cov_id = meta.attributes['content'].value
99-
if meta.attributes['name'].value == 'calibre:series':
100-
tmp_serie = meta.attributes['content'].value
101-
print("cov_id = ".format(cov_id))
102-
103-
items = mydoc.getElementsByTagName('item')
104-
for itm in items:
105-
if itm.attributes['id'].value == cov_id:
106-
print('cover = {}'.format(itm.attributes['href'].value))
107-
tmp_cover = create_thumbnail(tmpdir + '/' + itm.attributes['href'].value)
108-
except Exception:
109-
traceback.print_exc()
164+
infos = getEpubIfo(file)
165+
print(infos)
166+
if infos['guid'] is not None: tmp_guid = infos['guid']
167+
tmp_title = infos['title']
168+
tmp_authors = infos['authors']
169+
tmp_serie = infos['serie']
170+
tmp_cover = infos['cover']
110171

111172
if len(database.getBooks(tmp_guid)) > 0:
112173
tmp_guid = uid()

common.py

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,29 @@
55
import time
66
import datetime
77
import enum
8+
import vars
9+
import subprocess
810

911

10-
class SIZE_UNIT(enum.Enum):
11-
BYTES = 1
12-
KB = 2
13-
MB = 3
14-
GB = 4
15-
16-
17-
def convert_unit(size_in_bytes, unit):
18-
"""
19-
Convert the size from bytes to other units like KB, MB or GB
20-
21-
:param size_in_bytes:
22-
:param unit:
23-
:return:
24-
"""
25-
if unit == SIZE_UNIT.KB:
26-
return '{:.2f} Kb'.format(size_in_bytes/1024)
27-
elif unit == SIZE_UNIT.MB:
28-
return '{:.2f} Mb'.format(size_in_bytes/(1024*1024))
29-
elif unit == SIZE_UNIT.GB:
30-
return '{:.2f} Gb'.format(size_in_bytes/(1024*1024*1024))
31-
else:
32-
return '{} bytes'.format(size_in_bytes)
33-
34-
35-
def get_file_size(file_name):
12+
def get_file_size(file_name: str, human_readable: bool = True):
3613
"""
3714
Get file in size in given unit like KB, MB or GB
3815
3916
:param file_name:
40-
:param size_type:
17+
:param human_readable:
4118
:return:
4219
"""
4320
size = os.path.getsize(file_name)
44-
size_type = SIZE_UNIT.BYTES
45-
if size > (1024*1024*1024): size_type = SIZE_UNIT.GB
46-
elif size > (1024*1024): size_type = SIZE_UNIT.MB
47-
if size > 1024: size_type = SIZE_UNIT.KB
48-
return convert_unit(size, size_type)
21+
if human_readable is False:
22+
return size
23+
elif size > (1024*1024*1024):
24+
return '{:.2f} Gb'.format(size/(1024*1024*1024))
25+
elif size > (1024*1024):
26+
return '{:.2f} Mb'.format(size/(1024*1024))
27+
elif size > 1024:
28+
return '{:.2f} Kb'.format(size/1024)
29+
else:
30+
return '{} bytes'.format(size)
4931

5032

5133
def is_in(objet: dict, indexes: list):
@@ -130,4 +112,16 @@ def cleanStringForUrl(string: str):
130112
.replace('/', '_')\
131113
.replace('"', '_')\
132114
.replace(',', '_')\
133-
.replace('?', '_')
115+
.replace('?', '_')
116+
117+
118+
def deflate(src: str, dest: str):
119+
global env_vars
120+
list_args = list() # create list argument for external command execution
121+
list_args.append(env_vars['tools']['7zip'][os.name]['path']) # insert executable path
122+
temp_args = env_vars['tools']['7zip'][os.name]['params_deflate'].split(' ') # create table of raw command arguments
123+
for var in temp_args: # parse table of raw command arguments
124+
# insert parsed param
125+
list_args.append(var.replace('%input%', src).replace('%output%', dest))
126+
print(list_args)
127+
return subprocess.check_output(list_args, universal_newlines=True) # execute the command

editor/editing_pane.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import os
2+
import io
3+
import sys
4+
from PyQt5 import QtCore, QtGui, QtWidgets
5+
6+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
7+
from common import *
8+
9+
10+
class editorTabManager(QtWidgets.QTabWidget):
11+
def __init__(self, parent: any):
12+
QtWidgets.QTabWidget.__init__(self, parent)
13+
14+
def createPane(self, title: str, path: str):
15+
tab = QtWidgets.QWidget()
16+
# tab.setObjectName("tab")
17+
tab.setProperty('fileName', path)
18+
verticalLayout = QtWidgets.QVBoxLayout(tab)
19+
# verticalLayout.setObjectName("verticalLayout")
20+
scrollArea = QtWidgets.QScrollArea(tab)
21+
scrollArea.setMaximumSize(QtCore.QSize(16777215, 50))
22+
scrollArea.setWidgetResizable(True)
23+
# scrollArea.setObjectName("scrollArea")
24+
scrollAreaWidgetContents = QtWidgets.QWidget()
25+
scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 203, 48))
26+
# scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
27+
scrollArea.setWidget(scrollAreaWidgetContents)
28+
verticalLayout.addWidget(scrollArea)
29+
textEdit = QtWidgets.QTextEdit(tab)
30+
textEdit.setStyleSheet("background-color: rgb(154, 154, 154);\n"
31+
"color: rgb(0, 0, 0);")
32+
# textEdit.setObjectName("textEdit")
33+
print(path)
34+
with open(path, "r", encoding="utf8") as file:
35+
textEdit.setText(file.read())
36+
verticalLayout.addWidget(textEdit)
37+
self.addTab(tab, "")
38+
self.setTabText(self.indexOf(tab), title)
39+

0 commit comments

Comments
 (0)