Manga mode

Comics are parsed for images only
Miscellaneous fixes
This commit is contained in:
BasioMeusPuga
2019-01-14 15:54:29 +05:30
parent f997bc9c9a
commit 17f39c557b
18 changed files with 7580 additions and 7046 deletions

4
TODO
View File

@@ -69,7 +69,7 @@ TODO
Annotations
✓ Text
Annotation preview in listView
Disable buttons for annotations, search in images
Disable buttons for annotations, search in images
Adjust key navigation according to viewport dimensions
Redo context menu order
Filetypes:
@@ -80,6 +80,7 @@ TODO
✓ cbz, cbr support
✓ Keep font settings enabled but only for background color
✓ Double page view
✓ Manga mode
✓ mobi, azw support
Limit the extra files produced by KindleUnpack
Have them save to memory
@@ -98,7 +99,6 @@ TODO
Hide mousepointer more aggressively
Secondary:
Manga mode for comics
Double page view for books
Graphical themes
Change focus rectangle dimensions

View File

@@ -181,12 +181,12 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.bookToolBar.distractionFreeButton.triggered.connect(self.toggle_distraction_free)
self.bookToolBar.fullscreenButton.triggered.connect(self.set_fullscreen)
self.bookToolBar.singlePageButton.triggered.connect(self.change_page_view)
self.bookToolBar.doublePageButton.triggered.connect(self.change_page_view)
if self.settings['page_view_button'] == 'singlePageButton':
self.bookToolBar.singlePageButton.setChecked(True)
else:
self.bookToolBar.mangaModeButton.triggered.connect(self.change_page_view)
if self.settings['double_page_mode']:
self.bookToolBar.doublePageButton.setChecked(True)
if self.settings['manga_mode']:
self.bookToolBar.mangaModeButton.setChecked(True)
for count, i in enumerate(self.display_profiles):
self.bookToolBar.profileBox.setItemData(count, i, QtCore.Qt.UserRole)
@@ -210,12 +210,18 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
i[1].triggered.connect(self.modify_font)
self.alignment_dict[current_profile['text_alignment']].setChecked(True)
self.bookToolBar.zoomIn.triggered.connect(self.modify_comic_view)
self.bookToolBar.zoomOut.triggered.connect(self.modify_comic_view)
self.bookToolBar.fitWidth.triggered.connect(self.modify_comic_view)
self.bookToolBar.bestFit.triggered.connect(self.modify_comic_view)
self.bookToolBar.originalSize.triggered.connect(self.modify_comic_view)
self.bookToolBar.comicBGColor.clicked.connect(self.get_color)
self.bookToolBar.zoomIn.triggered.connect(
self.modify_comic_view)
self.bookToolBar.zoomOut.triggered.connect(
self.modify_comic_view)
self.bookToolBar.fitWidth.triggered.connect(
lambda: self.modify_comic_view(False))
self.bookToolBar.bestFit.triggered.connect(
lambda: self.modify_comic_view(False))
self.bookToolBar.originalSize.triggered.connect(
lambda: self.modify_comic_view(False))
self.bookToolBar.comicBGColor.clicked.connect(
self.get_color)
self.bookToolBar.colorBoxFG.clicked.connect(self.get_color)
self.bookToolBar.colorBoxBG.clicked.connect(self.get_color)
@@ -752,8 +758,19 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
#____________________________________________
def change_page_view(self):
self.settings['page_view_button'] = self.sender().objectName()
def change_page_view(self, key_pressed=False):
# Toggle Double page mode / manga mode on keypress
if key_pressed == QtCore.Qt.Key_D:
self.bookToolBar.doublePageButton.setChecked(
not self.bookToolBar.doublePageButton.isChecked())
if key_pressed == QtCore.Qt.Key_M:
self.bookToolBar.mangaModeButton.setChecked(
not self.bookToolBar.mangaModeButton.isChecked())
# Change settings according to the
# current state of each of the toolbar buttons
self.settings['double_page_mode'] = self.bookToolBar.doublePageButton.isChecked()
self.settings['manga_mode'] = self.bookToolBar.mangaModeButton.isChecked()
chapter_number = self.bookToolBar.tocBox.currentIndex()
# Switch page to whatever index is selected in the tocBox

View File

@@ -77,7 +77,7 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
current_page_index = all_pages.index(current_page)
double_page_mode = False
if (self.main_window.settings['page_view_button'] == 'doublePageButton'
if (self.main_window.settings['double_page_mode']
and (current_page_index != 0 and current_page_index != len(all_pages) - 1)):
double_page_mode = True
@@ -101,13 +101,25 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
next_page = all_pages[current_page_index + 1]
secondPixmap = page_loader(next_page)
# Pixmap height should be the greater of the 2 images
pixmap_height = firstPixmap.height()
if secondPixmap.height() > pixmap_height:
pixmap_height = secondPixmap.height()
bigPixmap = QtGui.QPixmap(
firstPixmap.width() + secondPixmap.width() + 5,
firstPixmap.height())
pixmap_height)
bigPixmap.fill(QtCore.Qt.transparent)
imagePainter = QtGui.QPainter(bigPixmap)
imagePainter.drawPixmap(0, 0, firstPixmap)
imagePainter.drawPixmap(firstPixmap.width() + 5, 0, secondPixmap)
manga_mode = self.main_window.settings['manga_mode']
if manga_mode:
imagePainter.drawPixmap(0, 0, secondPixmap)
imagePainter.drawPixmap(secondPixmap.width() + 4, 0, firstPixmap)
else:
imagePainter.drawPixmap(0, 0, firstPixmap)
imagePainter.drawPixmap(firstPixmap.width() + 4, 0, secondPixmap)
imagePainter.end()
return bigPixmap
@@ -236,6 +248,7 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
small_increment = maximum // 4
big_increment = maximum // 2
# Scrolling
if event.key() == QtCore.Qt.Key_Up:
scroller(small_increment, False)
if event.key() == QtCore.Qt.Key_Down:
@@ -243,6 +256,11 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
if event.key() == QtCore.Qt.Key_Space:
scroller(big_increment)
# Double page mode and manga mode
if event.key() in (QtCore.Qt.Key_D, QtCore.Qt.Key_M):
self.main_window.change_page_view(event.key())
# Image fit modes
view_modification_keys = (
QtCore.Qt.Key_Plus, QtCore.Qt.Key_Minus, QtCore.Qt.Key_Equal,
QtCore.Qt.Key_B, QtCore.Qt.Key_W, QtCore.Qt.Key_O)
@@ -291,16 +309,19 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
viewSubMenu.setIcon(
self.main_window.QImageFactory.get_image('mail-thread-watch'))
singlePageAction = doublePageAction = 'It\'s hammer time'
if self.main_window.settings['page_view_button'] == 'doublePageButton':
singlePageAction = viewSubMenu.addAction(
self.main_window.QImageFactory.get_image('page-single'),
self._translate('PliantQGraphicsView', 'Single page view'))
else:
doublePageAction = viewSubMenu.addAction(
self.main_window.QImageFactory.get_image('page-double'),
self._translate('PliantQGraphicsView', 'Double page view'))
doublePageAction = viewSubMenu.addAction(
self.main_window.QImageFactory.get_image('page-double'),
self._translate('PliantQGraphicsView', 'Double page mode (D)'))
doublePageAction.setCheckable(True)
doublePageAction.setChecked(
self.main_window.bookToolBar.doublePageButton.isChecked())
mangaModeAction = viewSubMenu.addAction(
self.main_window.QImageFactory.get_image('manga-mode'),
self._translate('PliantQGraphicsView', 'Manga mode (M)'))
mangaModeAction.setCheckable(True)
mangaModeAction.setChecked(
self.main_window.bookToolBar.mangaModeButton.isChecked())
viewSubMenu.addSeparator()
zoominAction = viewSubMenu.addAction(
@@ -333,11 +354,10 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
action = contextMenu.exec_(self.sender().mapToGlobal(position))
if action == singlePageAction:
self.main_window.bookToolBar.singlePageButton.trigger()
if action == doublePageAction:
self.main_window.bookToolBar.doublePageButton.trigger()
if action == mangaModeAction:
self.main_window.bookToolBar.mangaModeButton.trigger()
if action == saveAction:
dialog_prompt = self._translate('Main_UI', 'Save page as...')
@@ -708,7 +728,11 @@ class PliantWidgetsCommonFunctions:
# Special cases for double page view
def get_modifier():
if (self.main_window.settings['page_view_button'] == 'singlePageButton'
# if (self.main_window.settings['page_view_button'] == 'singlePageButton'
# or not self.are_we_doing_images_only):
# return 0
if (not self.main_window.settings['double_page_mode']
or not self.are_we_doing_images_only):
return 0

View File

@@ -36,16 +36,24 @@ class ParseCOMIC:
if self.book_extension[1] == '.cbz':
self.book = zipfile.ZipFile(
self.filename, mode='r', allowZip64=True)
self.image_list = [i.filename for i in self.book.infolist() if not i.is_dir()]
self.image_list = [
i.filename for i in self.book.infolist()
if not i.is_dir() and is_image(i.filename)]
elif self.book_extension[1] == '.cbr':
self.book = rarfile.RarFile(self.filename)
self.image_list = [i.filename for i in self.book.infolist() if not i.isdir()]
self.image_list = [
i.filename for i in self.book.infolist()
if not i.isdir() and is_image(i.filename)]
self.image_list.sort()
except: # Specifying no exception here is warranted
print('Cannot parse ' + self.filename)
return
if not self.image_list:
return False
return True
except: # Specifying no exception here is warranted
return False
def get_title(self):
title = os.path.basename(self.book_extension[0]).strip(' ')
@@ -76,3 +84,11 @@ class ParseCOMIC:
contents = [(f'Page {count + 1}', i) for count, i in enumerate(self.image_list)]
return contents, file_settings
def is_image(filename):
valid_image_extensions = ['.png', '.jpg', '.bmp']
if os.path.splitext(filename)[1].lower() in valid_image_extensions:
return True
else:
return False

View File

@@ -33,9 +33,9 @@ class ParseEPUB:
self.book_ref = EPUB(self.filename)
contents_found = self.book_ref.read_epub()
if not contents_found:
print('Cannot process: ' + self.filename)
return
return False
self.book = self.book_ref.book
return True
def get_title(self):
return self.book['title']

View File

@@ -32,9 +32,9 @@ class ParseFB2:
self.book_ref = FB2(self.filename)
contents_found = self.book_ref.read_fb2()
if not contents_found:
print('Cannot process: ' + self.filename)
return
return False
self.book = self.book_ref.book
return True
def get_title(self):
return self.book['title']

View File

@@ -55,9 +55,9 @@ class ParseMOBI:
self.book_ref = EPUB(self.epub_filepath)
contents_found = self.book_ref.read_epub()
if not contents_found:
print('Cannot process: ' + self.filename)
return
return False
self.book = self.book_ref.book
return True
def get_title(self):
return self.book['title']

View File

@@ -36,9 +36,10 @@ class ParsePDF:
def read_book(self):
self.book = popplerqt5.Poppler.Document.load(self.filename)
if not self.book:
return
return False
self.metadata = BeautifulSoup(self.book.metadata(), 'xml')
return True
def get_title(self):
try:

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22"
height="22"
version="1.1"
viewBox="0 0 22 22"
id="svg7"
sodipodi:docname="manga.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata11">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1586"
inkscape:window-height="856"
id="namedview9"
showgrid="false"
inkscape:zoom="10.727273"
inkscape:cx="11"
inkscape:cy="11"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg7" />
<defs
id="defs3">
<style
id="current-color-scheme"
type="text/css">
.ColorScheme-Text { color:#6e6e6e; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path
style="fill:#5c616c;fill-opacity:1"
class="ColorScheme-Text"
d="M 19,11 14,6 V 8 H 8 V 6 l -5,5 5,5 v -2 h 6 v 2 z"
id="path5" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 15 L 15 15 L 15 1 L 1 1 z M 3 3 L 7 3 L 7 13 L 3 13 L 3 3 z M 9 3 L 13 3 L 13 13 L 9 13 L 9 3 z" transform="translate(4 4)"/>
</svg>

Before

Width:  |  Height:  |  Size: 450 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" version="1.1" viewBox="0 0 22 22">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 19,11 14,6 V 8 H 8 V 6 l -5,5 5,5 v -2 h 6 v 2 z"/>
</svg>

After

Width:  |  Height:  |  Size: 382 B

View File

@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 2 1 L 2 15 L 14 15 L 14 1 L 2 1 z M 4 3 L 12 3 L 12 13 L 4 13 L 4 3 z" transform="translate(4 4)"/>
</svg>

Before

Width:  |  Height:  |  Size: 416 B

View File

@@ -1,12 +1,13 @@
<RCC>
<qresource prefix="images">
<file>DarkIcons/manga-mode.svg</file>
<file>LightIcons/manga-mode.svg</file>
<file>DarkIcons/search-word.svg</file>
<file>DarkIcons/search-word.svg</file>
<file>DarkIcons/search-case.svg</file>
<file>LightIcons/search-word.svg</file>
<file>LightIcons/search-case.svg</file>
<file>DarkIcons/page-single.svg</file>
<file>DarkIcons/page-double.svg</file>
<file>LightIcons/page-single.svg</file>
<file>LightIcons/page-double.svg</file>
<file>DarkIcons/about.svg</file>
<file>DarkIcons/switches.svg</file>

File diff suppressed because it is too large Load Diff

View File

@@ -125,8 +125,10 @@ class Settings:
self.parent.settings['consider_read_at'] = int(self.settings.value('considerReadAt', 95))
self.parent.settings['attenuate_titles'] = literal_eval(self.settings.value(
'attenuateTitles', 'False').capitalize())
self.parent.settings['page_view_button'] = self.settings.value(
'pageViewButton', 'singlePageButton')
self.parent.settings['double_page_mode'] = literal_eval(self.settings.value(
'doublePageMode', 'False').capitalize())
self.parent.settings['manga_mode'] = literal_eval(self.settings.value(
'mangaMode', 'False').capitalize())
self.settings.endGroup()
self.settings.beginGroup('dialogSettings')
@@ -208,7 +210,8 @@ class Settings:
self.settings.setValue('tocWithBookmarks', str(current_settings['toc_with_bookmarks']))
self.settings.setValue('scrollSpeed', current_settings['scroll_speed'])
self.settings.setValue('considerReadAt', current_settings['consider_read_at'])
self.settings.setValue('pageViewButton', current_settings['page_view_button'])
self.settings.setValue('mangaMode', str(current_settings['manga_mode']))
self.settings.setValue('doublePageMode', str(current_settings['double_page_mode']))
self.settings.endGroup()
self.settings.beginGroup('dialogSettings')

View File

@@ -192,7 +192,11 @@ class BookSorter:
# Everything following this is standard
# None values are accounted for here
book_ref.read_book()
is_valid = book_ref.read_book()
if not is_valid:
print('Cannot parse: ' + filename)
return
if book_ref.book:
this_book = {}

View File

@@ -209,52 +209,46 @@ class BookToolBar(QtWidgets.QToolBar):
i.setVisible(False)
# Comic view modification
# Single and double page view buttons
self.singlePageButton = QtWidgets.QAction(
image_factory.get_image('page-single'),
self._translate('BookToolBar', 'View as single page'),
self)
self.singlePageButton.setObjectName('singlePageButton')
self.singlePageButton.setCheckable(True)
self.doublePageButton = QtWidgets.QAction(
image_factory.get_image('page-double'),
self._translate('BookToolBar', 'View as double page'),
self._translate('BookToolBar', 'Double page mode (D)'),
self)
self.doublePageButton.setObjectName('doublePageButton')
self.doublePageButton.setCheckable(True)
self.pageViewButtons = QtWidgets.QActionGroup(self)
self.pageViewButtons.setExclusive(True)
self.pageViewButtons.addAction(self.singlePageButton)
self.pageViewButtons.addAction(self.doublePageButton)
self.mangaModeButton = QtWidgets.QAction(
image_factory.get_image('manga-mode'),
self._translate('BookToolBar', 'Manga mode (M)'),
self)
self.mangaModeButton.setObjectName('mangaModeButton')
self.mangaModeButton.setCheckable(True)
self.zoomIn = QtWidgets.QAction(
image_factory.get_image('zoom-in'),
self._translate('BookToolBar', 'Zoom in'),
self._translate('BookToolBar', 'Zoom in (+)'),
self)
self.zoomIn.setObjectName('zoomIn')
self.zoomOut = QtWidgets.QAction(
image_factory.get_image('zoom-out'),
self._translate('BookToolBar', 'Zoom Out'),
self._translate('BookToolBar', 'Zoom Out (-)'),
self)
self.zoomOut.setObjectName('zoomOut')
self.fitWidth = QtWidgets.QAction(
image_factory.get_image('zoom-fit-width'),
self._translate('BookToolBar', 'Fit Width'),
self._translate('BookToolBar', 'Fit Width (W)'),
self)
self.fitWidth.setObjectName('fitWidth')
self.fitWidth.setCheckable(True)
self.bestFit = QtWidgets.QAction(
image_factory.get_image('zoom-fit-best'),
self._translate('BookToolBar', 'Best Fit'),
self._translate('BookToolBar', 'Best Fit (B)'),
self)
self.bestFit.setObjectName('bestFit')
self.bestFit.setCheckable(True)
self.originalSize = QtWidgets.QAction(
image_factory.get_image('zoom-original'),
self._translate('BookToolBar', 'Original size'),
self._translate('BookToolBar', 'Original size (O)'),
self)
self.originalSize.setObjectName('originalSize')
self.originalSize.setCheckable(True)
@@ -264,8 +258,8 @@ class BookToolBar(QtWidgets.QToolBar):
self.comicBGColor.setObjectName('comicBGColor')
self.comicSeparator1 = self.addSeparator()
self.addAction(self.singlePageButton)
self.addAction(self.doublePageButton)
self.addAction(self.mangaModeButton)
self.comicSeparator2 = self.addSeparator()
self.addAction(self.zoomIn)
self.addAction(self.zoomOut)
@@ -276,8 +270,8 @@ class BookToolBar(QtWidgets.QToolBar):
self.comicBGColorAction = self.addWidget(self.comicBGColor)
self.comicActions = [
self.singlePageButton,
self.doublePageButton,
self.mangaModeButton,
self.comicBGColorAction,
self.zoomIn,
self.zoomOut,

View File

@@ -243,11 +243,16 @@ class Tab(QtWidgets.QWidget):
self.searchTimer.timeout.connect(self.set_search_options)
self.searchLineEdit.textChanged.connect(
lambda: self.searchLineEdit.setStyleSheet(QtWidgets.QLineEdit.styleSheet(self)))
self.searchLineEdit.textChanged.connect(lambda: self.searchTimer.start(500))
self.searchBookButton.clicked.connect(lambda: self.searchTimer.start(100))
self.caseSensitiveSearchButton.clicked.connect(lambda: self.searchTimer.start(100))
self.matchWholeWordButton.clicked.connect(lambda: self.searchTimer.start(100))
lambda: self.searchLineEdit.setStyleSheet(
QtWidgets.QLineEdit.styleSheet(self)))
self.searchLineEdit.textChanged.connect(
lambda: self.searchTimer.start(500))
self.searchBookButton.clicked.connect(
lambda: self.searchTimer.start(100))
self.caseSensitiveSearchButton.clicked.connect(
lambda: self.searchTimer.start(100))
self.matchWholeWordButton.clicked.connect(
lambda: self.searchTimer.start(100))
# Create tab in the central tab widget
title = self.metadata['title']
@@ -794,6 +799,7 @@ class PliantLabelWidget(QtWidgets.QLabel):
self.navigate_to_search_result(self.index)
QtWidgets.QLabel.mousePressEvent(self, QMouseEvent)
class PliantDockWidget(QtWidgets.QDockWidget):
def __init__(self, main_window, notes_only, contentView, parent=None):
super(PliantDockWidget, self).__init__()