Table multicolumn search, split models into new module

This commit is contained in:
BasioMeusPuga
2017-11-28 11:09:04 +05:30
parent 2ba10a75dd
commit 7aa9b9daff
4 changed files with 106 additions and 53 deletions

View File

@@ -136,6 +136,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.libraryToolBar.tableViewButton.triggered.connect(self.switch_library_view) self.libraryToolBar.tableViewButton.triggered.connect(self.switch_library_view)
self.libraryToolBar.settingsButton.triggered.connect(self.show_settings) self.libraryToolBar.settingsButton.triggered.connect(self.show_settings)
self.libraryToolBar.searchBar.textChanged.connect(self.lib_ref.update_proxymodel) self.libraryToolBar.searchBar.textChanged.connect(self.lib_ref.update_proxymodel)
self.libraryToolBar.searchBar.textChanged.connect(self.lib_ref.update_table_proxy_model)
self.libraryToolBar.sortingBox.activated.connect(self.lib_ref.update_proxymodel) self.libraryToolBar.sortingBox.activated.connect(self.lib_ref.update_proxymodel)
self.addToolBar(self.libraryToolBar) self.addToolBar(self.libraryToolBar)
@@ -192,7 +193,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# Init display models # Init display models
self.lib_ref.generate_model('build') self.lib_ref.generate_model('build')
self.lib_ref.create_tablemodel() # TODO - Make this accompany other proxy model generations self.lib_ref.create_table_model() # TODO - Make this accompany other proxy model generations
self.lib_ref.create_proxymodel() self.lib_ref.create_proxymodel()
# ListView # ListView
@@ -285,6 +286,12 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.sorterProgress.setVisible(False) self.sorterProgress.setVisible(False)
self.lib_ref.create_proxymodel() self.lib_ref.create_proxymodel()
# Create the table model
# Since images aren't displayed here, it's fast enough to not
# need addition to
# self.create_table_model()
self.lib_ref.create_table_model()
def delete_books(self): def delete_books(self):
selected_books = self.listView.selectedIndexes() selected_books = self.listView.selectedIndexes()
if selected_books: if selected_books:

View File

@@ -5,7 +5,7 @@ import pickle
import database import database
from PyQt5 import QtWidgets, QtGui, QtCore from PyQt5 import QtWidgets, QtGui, QtCore
from widgets import LibraryItemModel, LibraryTableModel from models import LibraryItemModel, LibraryTableModel, TableProxyModel
class Library: class Library:
@@ -22,6 +22,7 @@ class Library:
# because I kinda sorta NEED the match() method # because I kinda sorta NEED the match() method
if mode == 'build': if mode == 'build':
self.table_rows = []
self.view_model = LibraryItemModel() self.view_model = LibraryItemModel()
books = database.DatabaseFunctions( books = database.DatabaseFunctions(
@@ -126,11 +127,28 @@ class Library:
self.table_rows.append( self.table_rows.append(
(title, author, year, tags, path)) (title, author, year, tags, path))
def create_tablemodel(self): def create_table_model(self):
table_header = ['Title', 'Author', 'Year', 'Tags'] table_header = ['Title', 'Author', 'Year', 'Tags']
self.table_rows.sort(key=lambda x: x[0]) # self.table_rows.sort(key=lambda x: x[0])
self.table_model = LibraryTableModel(table_header, self.table_rows) self.table_model = LibraryTableModel(table_header, self.table_rows)
self.parent_window.tableView.setModel(self.table_model) self.create_table_proxy_model()
def create_table_proxy_model(self):
self.table_proxy_model = TableProxyModel()
self.table_proxy_model.setSourceModel(self.table_model)
self.parent_window.tableView.setModel(self.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, 3])
# 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())
def create_proxymodel(self): def create_proxymodel(self):
self.proxy_model = QtCore.QSortFilterProxyModel() self.proxy_model = QtCore.QSortFilterProxyModel()

76
models.py Normal file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env python3
from PyQt5 import QtCore, QtGui
class LibraryItemModel(QtGui.QStandardItemModel, QtCore.QAbstractItemModel):
def __init__(self, parent=None):
# We're using this to be able to access the match() method
super(LibraryItemModel, self).__init__(parent)
class LibraryTableModel(QtCore.QAbstractTableModel):
# TODO
# Speed up sorting
# Double clicking
# Auto resize with emphasis on Name
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()"))
class TableProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent=None):
super(TableProxyModel, self).__init__(parent)
self.filter_string = None
self.filter_columns = None
def setFilterParams(self, filter_text, filter_columns):
self.filter_string = filter_text.lower()
self.filter_columns = filter_columns
def filterAcceptsRow(self, row_num, parent):
if self.filter_string is None or self.filter_columns is None:
return True
model = self.sourceModel()
valid_indices = [model.index(row_num, i) for i in self.filter_columns]
valid_data = [model.data(i, QtCore.Qt.DisplayRole).lower() for i in valid_indices if model.data(i, QtCore.Qt.DisplayRole) is not None]
for i in valid_data:
if self.filter_string in i:
return True
return False

View File

@@ -723,51 +723,3 @@ class LibraryDelegate(QtWidgets.QStyledItemDelegate):
y_draw = option.rect.bottomRight().y() - 35 y_draw = option.rect.bottomRight().y() - 35
if current_chapter != 1: if current_chapter != 1:
painter.drawPixmap(x_draw, y_draw, read_icon) painter.drawPixmap(x_draw, y_draw, read_icon)
class LibraryItemModel(QtGui.QStandardItemModel, QtCore.QAbstractItemModel):
def __init__(self, parent=None):
# We're using this to be able to access the match() method
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()"))