Improve epub parsing, Table View for main library

This commit is contained in:
BasioMeusPuga
2017-11-27 02:18:09 +05:30
parent 255c5230b3
commit 75a851e62b
7 changed files with 203 additions and 83 deletions

View File

@@ -89,6 +89,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# Initialize settings dialog
self.settings_dialog = SettingsUI()
# Hide or show the main widget of the library
self.tableView.setVisible(False)
# Empty variables that will be infested soon
self.last_open_books = None
self.last_open_tab = None
@@ -176,22 +179,31 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# TODO
# Associate this with the library switcher
library_subclass = QtWidgets.QToolButton()
library_subclass.setIcon(QtGui.QIcon.fromTheme('view-readermode'))
library_subclass.setAutoRaise(True)
library_subclass.setPopupMode(QtWidgets.QToolButton.InstantPopup)
self.library_view_switch = QtWidgets.QToolButton()
self.library_view_switch.setIcon(QtGui.QIcon.fromTheme('view-readermode'))
self.library_view_switch.setAutoRaise(True)
self.library_view_switch.setPopupMode(QtWidgets.QToolButton.InstantPopup)
self.library_view_switch.triggered.connect(self.switch_library_view)
self.tabWidget.tabBar().setTabButton(0, QtWidgets.QTabBar.RightSide, library_subclass)
self.tabWidget.tabBar().setTabButton(
0, QtWidgets.QTabBar.RightSide, self.library_view_switch)
self.library_view_switch.clicked.connect(self.switch_library_view)
self.tabWidget.tabCloseRequested.connect(self.tab_close)
# Init display models
self.lib_ref.generate_model('build')
self.lib_ref.create_tablemodel() # TODO - Make this accompany other proxy model generations
self.lib_ref.create_proxymodel()
# ListView
self.listView.setGridSize(QtCore.QSize(175, 240))
self.listView.setMouseTracking(True)
self.listView.verticalScrollBar().setSingleStep(7)
self.listView.doubleClicked.connect(self.list_doubleclick)
self.listView.setItemDelegate(LibraryDelegate(self.temp_dir.path()))
self.lib_ref.generate_model('build')
self.lib_ref.create_proxymodel()
# TableView
self.tableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
# Keyboard shortcuts
self.ks_close_tab = QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+W'), self)
@@ -290,6 +302,16 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
msg_box.show()
msg_box.exec_()
def switch_library_view(self):
if self.listView.isVisible():
self.listView.setVisible(False)
self.tableView.setVisible(True)
self.libraryToolBar.sortingBoxAction.setVisible(False)
else:
self.listView.setVisible(True)
self.tableView.setVisible(False)
self.libraryToolBar.sortingBoxAction.setVisible(True)
def tab_switch(self):
if self.tabWidget.currentIndex() == 0:

View File

@@ -5,7 +5,7 @@ import pickle
import database
from PyQt5 import QtWidgets, QtGui, QtCore
from widgets import MyAbsModel
from widgets import LibraryItemModel, LibraryTableModel
class Library:
@@ -13,6 +13,8 @@ class Library:
self.parent_window = parent
self.view_model = None
self.proxy_model = None
self.table_model = None
self.table_rows = []
def generate_model(self, mode, parsed_books=None):
# The QlistView widget needs to be populated
@@ -20,7 +22,7 @@ class Library:
# because I kinda sorta NEED the match() method
if mode == 'build':
self.view_model = MyAbsModel()
self.view_model = LibraryItemModel()
books = database.DatabaseFunctions(
self.parent_window.database_path).fetch_data(
@@ -65,7 +67,7 @@ class Library:
author = i[2]
year = i[3]
path = i[4]
tags = i[6]
tags = i[7]
cover = i[9]
position = i[5]
@@ -120,6 +122,16 @@ class Library:
item.setIcon(QtGui.QIcon(img_pixmap))
self.view_model.appendRow(item)
# Path is just being sent. It is not being displayed
self.table_rows.append(
(title, author, year, tags, path))
def create_tablemodel(self):
table_header = ['Title', 'Author', 'Year', 'Tags']
self.table_rows.sort(key=lambda x: x[0])
self.table_model = LibraryTableModel(table_header, self.table_rows)
self.parent_window.tableView.setModel(self.table_model)
def create_proxymodel(self):
self.proxy_model = QtCore.QSortFilterProxyModel()
self.proxy_model.setSourceModel(self.view_model)

View File

@@ -12,6 +12,7 @@ import os
import re
import zipfile
import collections
from urllib.parse import unquote
import ebooklib.epub
@@ -101,37 +102,36 @@ class ParseEPUB:
return None
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()
def flatten_chapter(toc_element):
def flatten_section(toc_element):
output_list = []
for i in toc_element:
if isinstance(i, (tuple, list)):
output_list.extend(flatten_chapter(i))
output_list.extend(flatten_section(i))
else:
output_list.append(i)
return output_list
for i in self.book.toc:
if isinstance(i, (tuple, list)):
title = i[0].title
contents[title] = 'Composite Chapter'
# composite_chapter = flatten_chapter(i)
# composite_chapter_content = []
# for j in composite_chapter:
# href = j.href
# composite_chapter_content.append(
# self.book.get_item_with_href(href).get_content())
flattened = flatten_section(i)
for j in flattened:
title = j.title
href = unquote(j.href)
try:
content = self.book.get_item_with_href(href).get_content()
contents[title] = content.decode()
except AttributeError:
pass
# contents[title] = composite_chapter_content
else:
title = i.title
href = i.href
href = unquote(i.href)
try:
content = self.book.get_item_with_href(href).get_content()
if content:
@@ -139,7 +139,7 @@ class ParseEPUB:
else:
raise AttributeError
except AttributeError:
contents[title] = ''
contents[title] = 'Parse Error'
# Special settings that have to be returned with the file
# Referenced in sorter.py

View File

@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/main.ui'
# Form implementation generated from reading ui file 'raw/main.ui'
#
# Created by: PyQt5 UI code generator 5.9.1
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
@@ -23,10 +23,8 @@ class Ui_MainWindow(object):
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.gridLayout_2 = QtWidgets.QGridLayout(self.tab)
self.gridLayout_2.setObjectName("gridLayout_2")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.tab)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.listView = QtWidgets.QListView(self.tab)
self.listView.setFrameShape(QtWidgets.QFrame.NoFrame)
self.listView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
@@ -40,8 +38,20 @@ class Ui_MainWindow(object):
self.listView.setUniformItemSizes(True)
self.listView.setWordWrap(True)
self.listView.setObjectName("listView")
self.verticalLayout.addWidget(self.listView)
self.gridLayout_2.addLayout(self.verticalLayout, 0, 0, 1, 1)
self.horizontalLayout_2.addWidget(self.listView)
self.tableView = QtWidgets.QTableView(self.tab)
self.tableView.setFrameShape(QtWidgets.QFrame.NoFrame)
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.tableView.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed)
self.tableView.setAlternatingRowColors(True)
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableView.setGridStyle(QtCore.Qt.NoPen)
self.tableView.setSortingEnabled(True)
self.tableView.setWordWrap(False)
self.tableView.setObjectName("tableView")
self.tableView.horizontalHeader().setVisible(True)
self.tableView.verticalHeader().setVisible(False)
self.horizontalLayout_2.addWidget(self.tableView)
self.tabWidget.addTab(self.tab, "")
self.horizontalLayout.addWidget(self.tabWidget)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
@@ -64,4 +74,3 @@ class Ui_MainWindow(object):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Lector"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Library"))

View File

@@ -29,9 +29,7 @@
<attribute name="title">
<string>Library</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QListView" name="listView">
<property name="frameShape">
@@ -72,7 +70,39 @@
</property>
</widget>
</item>
</layout>
<item>
<widget class="QTableView" name="tableView">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="gridStyle">
<enum>Qt::NoPen</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>

View File

@@ -132,13 +132,18 @@ class BookSorter:
# None values are accounted for here
book_ref.read_book()
if book_ref.book:
title = book_ref.get_title().title()
author = book_ref.get_author()
if not author:
author = 'Unknown'
year = book_ref.get_year()
if not year:
try:
year = int(book_ref.get_year())
except (TypeError, ValueError):
year = 9999
isbn = book_ref.get_isbn()
# Different modes require different values

View File

@@ -297,7 +297,7 @@ class LibraryToolBar(QtWidgets.QToolBar):
# Add widgets
self.addWidget(spacer)
self.addWidget(self.sortingBox)
self.sortingBoxAction = self.addWidget(self.sortingBox)
self.addWidget(self.searchBar)
@@ -709,7 +709,49 @@ class LibraryDelegate(QtWidgets.QStyledItemDelegate):
painter.drawPixmap(x_draw, y_draw, read_icon)
class MyAbsModel(QtGui.QStandardItemModel, QtCore.QAbstractItemModel):
class LibraryItemModel(QtGui.QStandardItemModel, QtCore.QAbstractItemModel):
def __init__(self, parent=None):
# We're using this to be able to access the match() method
super(MyAbsModel, self).__init__(parent)
super(LibraryItemModel, self).__init__(parent)
class LibraryTableModel(QtCore.QAbstractTableModel):
# TODO
# Speed up sorting
# Associate with a proxy model to enable searching
# Double clicking
# Auto resize with emphasis on Name
# Hide path but send it anyway
def __init__(self, header_data, display_data, parent=None):
super(LibraryTableModel, self).__init__(parent)
self.header_data = header_data
self.display_data = display_data
def rowCount(self, parent):
return len(self.display_data)
def columnCount(self, parent):
return len(self.header_data)
def data(self, index, role):
if not index.isValid():
return None
if role == QtCore.Qt.DisplayRole:
value = self.display_data[index.row()][index.column()]
return value
else:
return QtCore.QVariant()
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self.header_data[col]
return None
def sort(self, col, order):
# self.emit(SIGNAL("layoutAboutToBeChanged()"))
self.display_data.sort(key=lambda x: x[col])
if order == QtCore.Qt.DescendingOrder:
self.display_data.sort(key=lambda x: x[col], reverse=True)
# self.emit(SIGNAL("layoutChanged()"))