Fairly substantial rewrite.

This commit is contained in:
BasioMeusPuga
2017-12-28 18:27:42 +05:30
parent 69392c5d4f
commit 01d1be9ddc
23 changed files with 1360 additions and 611 deletions

View File

@@ -1,16 +1,36 @@
#!/usr/bin/env python3
# This file is a part of Lector, a Qt based ebook reader
# Copyright (C) 2017 BasioMeusPuga
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# TODO
# Implement filterAcceptsRow for the view_model
import os
import pickle
import database
from PyQt5 import QtWidgets, QtGui, QtCore
from models import LibraryItemModel, MostExcellentTableModel, TableProxyModel
from PyQt5 import QtGui, QtCore
from models import MostExcellentTableModel, TableProxyModel
class Library:
def __init__(self, parent):
self.parent_window = parent
self.parent = parent
self.view_model = None
self.proxy_model = None
self.table_model = None
@@ -18,16 +38,12 @@ class Library:
self.table_rows = []
def generate_model(self, mode, parsed_books=None):
# The QlistView widget needs to be populated
# with a model that inherits from QAbstractItemModel
# because I kinda sorta NEED the match() method
if mode == 'build':
self.table_rows = []
self.view_model = LibraryItemModel()
self.view_model = QtGui.QStandardItemModel()
books = database.DatabaseFunctions(
self.parent_window.database_path).fetch_data(
self.parent.database_path).fetch_data(
('*',),
'books',
{'Title': ''},
@@ -43,20 +59,19 @@ class Library:
# database using background threads
books = []
for i in parsed_books:
parsed_title = parsed_books[i]['title']
parsed_author = parsed_books[i]['author']
parsed_year = parsed_books[i]['year']
parsed_path = parsed_books[i]['path']
parsed_position = None
parsed_isbn = parsed_books[i]['isbn']
parsed_tags = None
parsed_hash = i
parsed_cover = parsed_books[i]['cover_image']
for i in parsed_books.items():
# Scheme
# 1: Title, 2: Author, 3: Year, 4: Path
# 5: Position, 6: isbn, 7: Tags, 8: Hash
# 9: CoverImage
_tags = i[1]['tags']
if _tags:
_tags = ', '.join([j for j in _tags if j])
books.append([
None, parsed_title, parsed_author, parsed_year, parsed_path,
parsed_position, parsed_isbn, parsed_tags, parsed_hash, parsed_cover])
None, i[1]['title'], i[1]['author'], i[1]['year'], i[1]['path'],
None, i[1]['isbn'], _tags, i[0], i[1]['cover_image']])
else:
return
@@ -134,7 +149,7 @@ class Library:
def create_table_model(self):
table_header = ['Title', 'Author', 'Status', 'Year', 'Tags']
self.table_model = MostExcellentTableModel(
table_header, self.table_rows, self.parent_window.temp_dir.path())
table_header, self.table_rows, self.parent.temp_dir.path())
self.create_table_proxy_model()
def create_table_proxy_model(self):
@@ -142,38 +157,73 @@ class Library:
self.table_proxy_model.setSourceModel(self.table_model)
self.table_proxy_model.setSortCaseSensitivity(False)
self.table_proxy_model.sort(0, QtCore.Qt.AscendingOrder)
self.parent_window.tableView.setModel(self.table_proxy_model)
self.parent_window.tableView.horizontalHeader().setSortIndicator(
self.parent.tableView.setModel(self.table_proxy_model)
self.parent.tableView.horizontalHeader().setSortIndicator(
0, QtCore.Qt.AscendingOrder)
self.update_table_proxy_model()
def update_table_proxy_model(self):
self.table_proxy_model.invalidateFilter()
self.table_proxy_model.setFilterParams(
self.parent_window.libraryToolBar.searchBar.text(), [0, 1, 4])
self.parent.libraryToolBar.searchBar.text(), [0, 1, 4])
# This isn't needed, but it forces a model update every time the
# text in the line edit changes. So I guess it is needed.
self.table_proxy_model.setFilterFixedString(
self.parent_window.libraryToolBar.searchBar.text())
self.parent.libraryToolBar.searchBar.text())
def create_proxymodel(self):
self.proxy_model = QtCore.QSortFilterProxyModel()
self.proxy_model.setSourceModel(self.view_model)
self.proxy_model.setSortCaseSensitivity(False)
s = QtCore.QSize(160, 250) # Set icon sizing here
self.parent_window.listView.setIconSize(s)
self.parent_window.listView.setModel(self.proxy_model)
self.parent.listView.setIconSize(s)
self.parent.listView.setModel(self.proxy_model)
self.update_proxymodel()
def update_proxymodel(self):
self.proxy_model.setFilterRole(QtCore.Qt.UserRole + 4)
self.proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.proxy_model.setFilterWildcard(
self.parent_window.libraryToolBar.searchBar.text())
self.parent.libraryToolBar.searchBar.text())
self.parent_window.statusMessage.setText(
self.parent.statusMessage.setText(
str(self.proxy_model.rowCount()) + ' books')
# Sorting according to roles and the drop down in the library
self.proxy_model.setSortRole(
QtCore.Qt.UserRole + self.parent_window.libraryToolBar.sortingBox.currentIndex())
QtCore.Qt.UserRole + self.parent.libraryToolBar.sortingBox.currentIndex())
self.proxy_model.sort(0)
def prune_models(self, valid_paths):
# To be executed when the library is updated by folder
# All files in unselected directories will have to be removed
# from both of the models
# They will also have to be deleted from the library
valid_paths = set(valid_paths)
# Get all paths in the dictionary from either of the models
# self.table_rows has all file metadata in position 5
all_paths = [i[5]['path'] for i in self.table_rows]
all_paths = set(all_paths)
invalid_paths = all_paths - valid_paths
# Remove invalid paths from both of the models
self.table_rows = [
i for i in self.table_rows if i[5]['path'] not in invalid_paths]
deletable_persistent_indexes = []
for i in range(self.view_model.rowCount()):
item = self.view_model.item(i)
path = item.data(QtCore.Qt.UserRole + 3)['path']
if path in invalid_paths:
deletable_persistent_indexes.append(
QtCore.QPersistentModelIndex(item.index()))
if deletable_persistent_indexes:
for i in deletable_persistent_indexes:
self.view_model.removeRow(i.row())
# Remove invalid paths from the database as well
database.DatabaseFunctions(
self.parent.database_path).delete_from_database('Path', invalid_paths)