Skip to content

Commit

Permalink
tableview: Automaticaly switch header sorting on/off
Browse files Browse the repository at this point in the history
  • Loading branch information
ales-erjavec committed Mar 17, 2023
1 parent 4c40093 commit a4c3cea
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 40 deletions.
15 changes: 0 additions & 15 deletions Orange/widgets/data/owtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,6 @@ def _setup_table_view(self):
else:
view.setItemDelegate(TableDataDelegate(view))

# Enable/disable view sorting based on data's type
view.setSortingEnabled(is_sortable(data))
header = view.horizontalHeader()
header.setSectionsClickable(is_sortable(data))
header.setSortIndicatorShown(is_sortable(data))

view.setModel(datamodel)

vheader = view.verticalHeader()
Expand Down Expand Up @@ -393,15 +387,6 @@ def send_report(self):
self.report_table(self.view)


def is_sortable(table):
if isinstance(table, SqlTable):
return False
elif isinstance(table, Orange.data.Table):
return True
else:
return False


if __name__ == "__main__": # pragma: no cover
WidgetPreview(OWTable).run(
input_data=Table("iris"),
Expand Down
9 changes: 0 additions & 9 deletions Orange/widgets/data/utils/tablesummary.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,6 @@ def parts(density, col_dist):
return Summary(n_instances, domain, X_part, Y_part, M_part)


def is_sortable(table: Table) -> bool:
if isinstance(table, SqlTable):
return False
elif isinstance(table, Table):
return True
else:
return False


def format_summary(summary: Union[ApproxSummary, Summary]) -> List[str]:
def format_part(part: Optional[_ArrayStat]) -> str:
if isinstance(part, DenseArray):
Expand Down
48 changes: 45 additions & 3 deletions Orange/widgets/data/utils/tableview.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import sys
from itertools import chain, starmap
from typing import Sequence, Tuple, cast
from typing import Sequence, Tuple, cast, Optional

import numpy as np

from AnyQt.QtCore import (
Qt, QObject, QEvent, QSize, QAbstractProxyModel, QItemSelection,
QItemSelectionModel, QItemSelectionRange
QItemSelectionModel, QItemSelectionRange, QAbstractItemModel
)
from AnyQt.QtGui import QPainter
from AnyQt.QtWidgets import (
QStyle, QWidget, QStyleOptionHeader, QAbstractButton
)

import Orange.data
import Orange.data.sql.table

from Orange.widgets.data.utils.models import RichTableModel
from Orange.widgets.utils.itemmodels import TableModel
from Orange.widgets.utils.itemselectionmodel import (
Expand Down Expand Up @@ -99,13 +102,33 @@ def cornerButtonClicked(self):
self.selectAll()


def source_model(model: QAbstractItemModel) -> Optional[QAbstractItemModel]:
while isinstance(model, QAbstractProxyModel):
model = model.sourceModel()
return model


def is_table_sortable(table):
if isinstance(table, Orange.data.sql.table.SqlTable):
return False
elif isinstance(table, Orange.data.Table):
return True
else:
return False


class RichTableView(DataTableView):
"""
The preferred table view for RichTableModel.
Handles the display of variable's labels keys in top left corner.
"""
def setModel(self, model: RichTableModel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
header = self.horizontalHeader()
header.setSortIndicator(-1, Qt.AscendingOrder)

def setModel(self, model: QAbstractItemModel):
current = self.model()
if current is not None:
current.headerDataChanged.disconnect(self.__headerDataChanged)
Expand All @@ -117,6 +140,25 @@ def setModel(self, model: RichTableModel):
sel_model = BlockSelectionModel(model, selectBlocks=not select_rows)
self.setSelectionModel(sel_model)

sortable = self.isModelSortable(model)
self.setSortingEnabled(sortable)
header = self.horizontalHeader()
header.setSectionsClickable(sortable)
header.setSortIndicatorShown(sortable)

def isModelSortable(self, model: QAbstractItemModel) -> bool:
"""
Should the `model` be sortable via the view header click.
This predicate is called when a model is set on the view and
enables/disables the model sorting and header section sort indicators.
"""
model = source_model(model)
if isinstance(model, TableModel):
table = model.source
return is_table_sortable(table)
return False

def __headerDataChanged(
self,
orientation: Qt.Orientation,
Expand Down
13 changes: 0 additions & 13 deletions Orange/widgets/obsolete/owtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,7 @@ def _setup_table_view(self, view, data):
else:
view.setItemDelegate(TableDataDelegate(view))

# Enable/disable view sorting based on data's type
view.setSortingEnabled(is_sortable(data))
header = view.horizontalHeader()
header.setSectionsClickable(is_sortable(data))
header.setSortIndicatorShown(is_sortable(data))
header.sortIndicatorChanged.connect(self.update_selection)

view.setModel(datamodel)
Expand Down Expand Up @@ -526,15 +522,6 @@ def send_report(self):
self.report_table(view)


def is_sortable(table):
if isinstance(table, SqlTable):
return False
elif isinstance(table, Orange.data.Table):
return True
else:
return False


if __name__ == "__main__": # pragma: no cover
WidgetPreview(OWDataTable).run(
insert_dataset=[
Expand Down

0 comments on commit a4c3cea

Please sign in to comment.