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.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_table_proxy_model)
self.libraryToolBar.sortingBox.activated.connect(self.lib_ref.update_proxymodel)
self.addToolBar(self.libraryToolBar)
@@ -192,7 +193,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# 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_table_model() # TODO - Make this accompany other proxy model generations
self.lib_ref.create_proxymodel()
# ListView
@@ -285,6 +286,12 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.sorterProgress.setVisible(False)
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):
selected_books = self.listView.selectedIndexes()
if selected_books:

View File

@@ -5,7 +5,7 @@ import pickle
import database
from PyQt5 import QtWidgets, QtGui, QtCore
from widgets import LibraryItemModel, LibraryTableModel
from models import LibraryItemModel, LibraryTableModel, TableProxyModel
class Library:
@@ -22,6 +22,7 @@ class Library:
# because I kinda sorta NEED the match() method
if mode == 'build':
self.table_rows = []
self.view_model = LibraryItemModel()
books = database.DatabaseFunctions(
@@ -126,11 +127,28 @@ class Library:
self.table_rows.append(
(title, author, year, tags, path))
def create_tablemodel(self):
def create_table_model(self):
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.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):
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
if current_chapter != 1:
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()"))