1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2024-11-05 07:49:02 +00:00
dupeguru/qtlib/table.py

172 lines
5.5 KiB
Python
Raw Normal View History

2019-09-10 00:54:28 +00:00
# Created By: Virgil Dupras
# Created On: 2009-11-01
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
2019-09-10 00:54:28 +00:00
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import (
Qt,
QAbstractTableModel,
QModelIndex,
QItemSelectionModel,
QItemSelection,
)
2019-09-10 00:54:28 +00:00
from .column import Columns
2019-09-10 00:54:28 +00:00
class Table(QAbstractTableModel):
# Flags you want when index.isValid() is False. In those cases, _getFlags() is never called.
INVALID_INDEX_FLAGS = Qt.ItemIsEnabled
COLUMNS = []
2019-09-10 00:54:28 +00:00
def __init__(self, model, view, **kwargs):
super().__init__(**kwargs)
self.model = model
self.view = view
self.view.setModel(self)
self.model.view = self
if hasattr(self.model, "columns"):
self.columns = Columns(
self.model.columns, self.COLUMNS, view.horizontalHeader()
)
self.view.selectionModel().selectionChanged[
(QItemSelection, QItemSelection)
].connect(self.selectionChanged)
2019-09-10 00:54:28 +00:00
def _updateModelSelection(self):
# Takes the selection on the view's side and update the model with it.
# an _updateViewSelection() call will normally result in an _updateModelSelection() call.
# to avoid infinite loops, we check that the selection will actually change before calling
# model.select()
newIndexes = [
modelIndex.row() for modelIndex in self.view.selectionModel().selectedRows()
]
2019-09-10 00:54:28 +00:00
if newIndexes != self.model.selected_indexes:
self.model.select(newIndexes)
2019-09-10 00:54:28 +00:00
def _updateViewSelection(self):
# Takes the selection on the model's side and update the view with it.
newSelection = QItemSelection()
columnCount = self.columnCount(QModelIndex())
for index in self.model.selected_indexes:
newSelection.select(
self.createIndex(index, 0), self.createIndex(index, columnCount - 1)
)
self.view.selectionModel().select(
newSelection, QItemSelectionModel.ClearAndSelect
)
2019-09-10 00:54:28 +00:00
if len(newSelection.indexes()):
currentIndex = newSelection.indexes()[0]
self.view.selectionModel().setCurrentIndex(
currentIndex, QItemSelectionModel.Current
)
2019-09-10 00:54:28 +00:00
self.view.scrollTo(currentIndex)
# --- Data Model methods
2019-09-10 00:54:28 +00:00
# Virtual
def _getData(self, row, column, role):
if role in (Qt.DisplayRole, Qt.EditRole):
attrname = column.name
return row.get_cell_value(attrname)
elif role == Qt.TextAlignmentRole:
return column.alignment
return None
2019-09-10 00:54:28 +00:00
# Virtual
def _getFlags(self, row, column):
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if row.can_edit_cell(column.name):
flags |= Qt.ItemIsEditable
return flags
2019-09-10 00:54:28 +00:00
# Virtual
def _setData(self, row, column, value, role):
if role == Qt.EditRole:
attrname = column.name
if attrname == "from":
attrname = "from_"
2019-09-10 00:54:28 +00:00
setattr(row, attrname, value)
return True
return False
2019-09-10 00:54:28 +00:00
def columnCount(self, index):
return self.model.columns.columns_count()
2019-09-10 00:54:28 +00:00
def data(self, index, role):
if not index.isValid():
return None
row = self.model[index.row()]
column = self.model.columns.column_by_index(index.column())
return self._getData(row, column, role)
2019-09-10 00:54:28 +00:00
def flags(self, index):
if not index.isValid():
return self.INVALID_INDEX_FLAGS
row = self.model[index.row()]
column = self.model.columns.column_by_index(index.column())
return self._getFlags(row, column)
2019-09-10 00:54:28 +00:00
def headerData(self, section, orientation, role):
if orientation != Qt.Horizontal:
return None
if section >= self.model.columns.columns_count():
return None
column = self.model.columns.column_by_index(section)
if role == Qt.DisplayRole:
return column.display
elif role == Qt.TextAlignmentRole:
return column.alignment
else:
return None
2019-09-10 00:54:28 +00:00
def revert(self):
self.model.cancel_edits()
2019-09-10 00:54:28 +00:00
def rowCount(self, index):
if index.isValid():
return 0
return len(self.model)
2019-09-10 00:54:28 +00:00
def setData(self, index, value, role):
if not index.isValid():
return False
row = self.model[index.row()]
column = self.model.columns.column_by_index(index.column())
return self._setData(row, column, value, role)
2019-09-10 00:54:28 +00:00
def sort(self, section, order):
column = self.model.columns.column_by_index(section)
attrname = column.name
self.model.sort_by(attrname, desc=order == Qt.DescendingOrder)
2019-09-10 00:54:28 +00:00
def submit(self):
self.model.save_edits()
return True
# --- Events
2019-09-10 00:54:28 +00:00
def selectionChanged(self, selected, deselected):
self._updateModelSelection()
# --- model --> view
2019-09-10 00:54:28 +00:00
def refresh(self):
self.beginResetModel()
self.endResetModel()
self._updateViewSelection()
2019-09-10 00:54:28 +00:00
def show_selected_row(self):
if self.model.selected_index is not None:
self.view.showRow(self.model.selected_index)
2019-09-10 00:54:28 +00:00
def start_editing(self):
self.view.editSelected()
2019-09-10 00:54:28 +00:00
def stop_editing(self):
self.view.setFocus() # enough to stop editing
2019-09-10 00:54:28 +00:00
def update_selection(self):
self._updateViewSelection()