class OWDataSort(OWWidget): contextHandlers = { "": DomainContextHandler( "", ["sortroles"] ) } settingsList = ["autoCommit"] def __init__(self, parent=None, signalManger=None, title="Data Sort"): super(OWDataSort, self).__init__(parent, signalManger, title, wantMainArea=False) #: Mapping (feature.name, feature.var_type) to (sort_index, sort_order) #: where sirt index is the position of the feature in the sortByModel #: and sort_order the Qt.SortOrder flag self.sortroles = {} self.autoCommit = False self._outputChanged = False box = OWGUI.widgetBox(self.controlArea, "Sort By Features") self.sortByView = QListView() self.sortByView.setItemDelegate(SortParamDelegate(self)) self.sortByView.setSelectionMode(QListView.ExtendedSelection) self.sortByView.setDragDropMode(QListView.DragDrop) self.sortByView.setDefaultDropAction(Qt.MoveAction) self.sortByView.viewport().setAcceptDrops(True) self.sortByModel = VariableListModel( flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled | Qt.ItemIsEditable ) self.sortByView.setModel(self.sortByModel) box.layout().addWidget(self.sortByView) box = OWGUI.widgetBox(self.controlArea, "Unused Features") self.unusedView = QListView() self.unusedView.setSelectionMode(QListView.ExtendedSelection) self.unusedView.setDragDropMode(QListView.DragDrop) self.unusedView.setDefaultDropAction(Qt.MoveAction) self.unusedView.viewport().setAcceptDrops(True) self.unusedModel = VariableListModel( flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled ) self.unusedView.setModel(self.unusedModel) box.layout().addWidget(self.unusedView) box = OWGUI.widgetBox(self.controlArea, "Output") cb = OWGUI.checkBox(box, self, "autoCommit", "Auto commit") b = OWGUI.button(box, self, "Commit", callback=self.commit) OWGUI.setStopper(self, b, cb, "_outputChanged", callback=self.commit) def setData(self, data): """ Set the input data. """ self._storeRoles() self.closeContext("") self.data = data if data is not None: self.openContext("", data) domain = data.domain features = (domain.variables + domain.class_vars + domain.get_metas().values()) sort_by = [] unused = [] for feat in features: hint = self.sortroles.get((feat.name, feat.var_type), None) if hint is not None: index, order = hint sort_by.append((feat, index, order)) else: unused.append(feat) sort_by = sorted(sort_by, key=itemgetter(1)) self.sortByModel[:] = [feat for feat, _, _ in sort_by] self.unusedModel[:] = unused # Restore the sort orders for i, (_, _, order) in enumerate(sort_by): index = self.sortByModel.index(i, 0) self.sortByModel.setData(index, order, SortOrderRole) self.commit() def _invalidate(self): if self.autoCommit: self.commit() else: self._outputChanged = True def _sortingParams(self): params = [] for i, feature in enumerate(self.sortByModel): index = self.sortByModel.index(i, 0) order = toSortOrder(index.data(SortOrderRole)) params.append((feature, order)) return params def commit(self): params = self._sortingParams() if self.data: instances = sorted(self.data, key=sort_key(params)) data = Orange.data.Table(self.data.domain, instances) else: data = self.data self.send("Data", data) def _storeRoles(self): """ Store the sorting roles back into the stored settings. """ roles = {} for i, feature in enumerate(self.sortByModel): index = self.sortByModel.index(i, 0) order = toSortOrder(index.data(SortOrderRole)) roles[(feature.name, feature.var_type)] = (i, int(order)) self.sortroles = roles def getSettings(self, *args, **kwargs): self._storeRoles() return OWWidget.getSettings(self, *args, **kwargs)
class OWGroupBy(OWWidget): contextHandlers = {"": DomainContextHandler("", ["hints"])} settingsList = [] def __init__(self, parent=None, signalManager=None, title="Group By"): OWWidget.__init__(self, parent, signalManager, title, wantMainArea=False) self.inputs = [("Data", Table, self.set_data)] self.outputs = [("Data", Table)] self.auto_commit = True self.hints = {} self.state_changed_flag = False self.loadSettings() ############# # Data Models ############# self.group_list = VariableListModel(parent=self, flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \ Qt.ItemIsDragEnabled ) self.aggregate_list = VariableAggragateModel(parent=self, flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \ Qt.ItemIsDragEnabled | \ Qt.ItemIsEditable) self.aggregate_delegate = AggregateDelegate() ##### # GUI ##### box = OWGUI.widgetBox(self.controlArea, "Group By Attributes") self.group_view = QListView() self.group_view.setSelectionMode(QListView.ExtendedSelection) self.group_view.setDragDropMode(QListView.DragDrop) self.group_view.setModel(self.group_list) # self.group_view.setDragDropOverwriteMode(True) self.group_view.setDefaultDropAction(Qt.MoveAction) self.group_view.viewport().setAcceptDrops(True) # self.group_view.setDropIndicatorShown(True) self.group_view.setToolTip("A set of attributes to group by (drag \ values to 'Aggregate Attributes' to remove them from this group).") box.layout().addWidget(self.group_view) box = OWGUI.widgetBox(self.controlArea, "Aggregate Attributes") self.aggregate_view = AggregateListView() self.aggregate_view.setSelectionMode(QListView.ExtendedSelection) self.aggregate_view.setDragDropMode(QListView.DragDrop) self.aggregate_view.setItemDelegate(self.aggregate_delegate) self.aggregate_view.setModel(self.aggregate_list) self.aggregate_view.setEditTriggers(QListView.DoubleClicked | QListView.EditKeyPressed) # self.aggregate_view.setDragDropOverwriteMode(False) self.aggregate_view.setDefaultDropAction(Qt.MoveAction) self.aggregate_view.viewport().setAcceptDrops(True) self.aggregate_view.setToolTip("Aggregated attributes.") box.layout().addWidget(self.aggregate_view) OWGUI.rubber(self.controlArea) box = OWGUI.widgetBox(self.controlArea, "Commit") cb = OWGUI.checkBox( box, self, "auto_commit", "Commit on input change.", tooltip="Send the data on output on change of input.", callback=self.commit_if) b = OWGUI.button(box, self, "Commit", callback=self.commit, tooltip="Send data on output.", autoDefault=True) # OWGUI.setStopper(self, b, cb, "state_changed_flag", # callback=self.commit) def set_data(self, data=None): """ Set the input data for the widget. """ self.update_hints() self.closeContext("") self.clear() if data is not None: self.init_with_data(data) self.openContext("", data) self.init_state_from_hints() self.commit_if() def init_with_data(self, data): """ Init widget state from data """ attrs = data.domain.variables + data.domain.get_metas().values() # self.group_list.set_items(attrs) self.all_attrs = attrs self.hints = dict([((a.name, a.varType), ("group_by", "First")) for a in attrs]) self.data = data def init_state_from_hints(self): """ Init the group and aggregate from hints (call after openContext) """ group = [] aggregate = [] aggregate_hint = {} for a in self.all_attrs: try: place, hint = self.hints.get((a.name, a.var_type), ("group_by", DEFAULT_METHOD)) except Exception: place, hint = ("group_by", DEFAULT_METHOD) if place == "group_by": group.append(a) else: aggregate.append(a) aggregate_hint[a] = hint self.group_list[:] = group self.aggregate_list[:] = aggregate for i, a in enumerate(group): self.group_list.setData(self.group_list.index(i), aggregate_hint[a], AggregateMethodRole) for i, a in enumerate(aggregate): self.aggregate_list.setData(self.aggregate_list.index(i), aggregate_hint[a], AggregateMethodRole) def update_hints(self): for i, var in enumerate(self.group_list): self.hints[var.name, var.var_type] = \ ("group_by", str(self.group_list.data( \ self.group_list.index(i), AggregateMethodRole).toPyObject())) for i, var in enumerate(self.aggregate_list): self.hints[var.name, var.var_type] = \ ("aggregate", str(self.aggregate_list.data( \ self.aggregate_list.index(i), AggregateMethodRole).toPyObject())) def clear(self): """ Clear the widget state. """ self.data = None self.group_list[:] = [] #clear() self.aggregate_list[:] = [] #.clear() self.all_attrs = [] self.hints = {} def get_aggregates_from_hints(self): aggregates = {} for i, v in enumerate(self.aggregate_list): _, hint = self.hints.get((v.name, v.var_type), ("", DEFAULT_METHOD)) aggregates[v] = hint.lower() return aggregates def commit_if(self): if self.auto_commit: self.commit() else: self.state_changed_flag = True def commit(self): self.update_hints() if self.data is not None: group = list(self.group_list) aggregates = self.get_aggregates_from_hints() print aggregates data = utils.group_by(self.data, group, attr_aggregate=aggregates) else: data = None self.send("Data", data) self.state_changed_flag = False
class OWGroupBy(OWWidget): contextHandlers = {"": DomainContextHandler("", ["hints"])} settingsList = [] def __init__(self, parent=None, signalManager=None, title="Group By"): OWWidget.__init__(self, parent, signalManager, title, wantMainArea=False) self.inputs = [("Data", Table, self.set_data)] self.outputs = [("Data", Table)] self.auto_commit = True self.hints = {} self.state_changed_flag = False self.loadSettings() ############# # Data Models ############# self.group_list = VariableListModel(parent=self, flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \ Qt.ItemIsDragEnabled ) self.aggregate_list = VariableAggragateModel(parent=self, flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \ Qt.ItemIsDragEnabled | \ Qt.ItemIsEditable) self.aggregate_delegate = AggregateDelegate() ##### # GUI ##### box = OWGUI.widgetBox(self.controlArea, "Group By Attributes") self.group_view = QListView() self.group_view.setSelectionMode(QListView.ExtendedSelection) self.group_view.setDragDropMode(QListView.DragDrop) self.group_view.setModel(self.group_list) # self.group_view.setDragDropOverwriteMode(True) self.group_view.setDefaultDropAction(Qt.MoveAction) self.group_view.viewport().setAcceptDrops(True) # self.group_view.setDropIndicatorShown(True) self.group_view.setToolTip("A set of attributes to group by (drag \ values to 'Aggregate Attributes' to remove them from this group).") box.layout().addWidget(self.group_view) box = OWGUI.widgetBox(self.controlArea, "Aggregate Attributes") self.aggregate_view = AggregateListView() self.aggregate_view.setSelectionMode(QListView.ExtendedSelection) self.aggregate_view.setDragDropMode(QListView.DragDrop) self.aggregate_view.setItemDelegate(self.aggregate_delegate) self.aggregate_view.setModel(self.aggregate_list) self.aggregate_view.setEditTriggers(QListView.DoubleClicked | QListView.EditKeyPressed) # self.aggregate_view.setDragDropOverwriteMode(False) self.aggregate_view.setDefaultDropAction(Qt.MoveAction) self.aggregate_view.viewport().setAcceptDrops(True) self.aggregate_view.setToolTip("Aggregated attributes.") box.layout().addWidget(self.aggregate_view) OWGUI.rubber(self.controlArea) box = OWGUI.widgetBox(self.controlArea, "Commit") cb = OWGUI.checkBox(box, self, "auto_commit", "Commit on input change.", tooltip="Send the data on output on change of input.", callback=self.commit_if ) b = OWGUI.button(box, self, "Commit", callback=self.commit, tooltip="Send data on output.", autoDefault=True) # OWGUI.setStopper(self, b, cb, "state_changed_flag", # callback=self.commit) def set_data(self, data=None): """ Set the input data for the widget. """ self.update_hints() self.closeContext("") self.clear() if data is not None: self.init_with_data(data) self.openContext("", data) self.init_state_from_hints() self.commit_if() def init_with_data(self, data): """ Init widget state from data """ attrs = data.domain.variables + data.domain.get_metas().values() # self.group_list.set_items(attrs) self.all_attrs = attrs self.hints = dict([((a.name, a.varType), ("group_by", "First")) for a in attrs]) self.data = data def init_state_from_hints(self): """ Init the group and aggregate from hints (call after openContext) """ group = [] aggregate = [] aggregate_hint = {} for a in self.all_attrs: try: place, hint = self.hints.get((a.name, a.var_type), ("group_by", DEFAULT_METHOD)) except Exception: place, hint = ("group_by", DEFAULT_METHOD) if place == "group_by": group.append(a) else: aggregate.append(a) aggregate_hint[a] = hint self.group_list[:] = group self.aggregate_list[:] = aggregate for i, a in enumerate(group): self.group_list.setData(self.group_list.index(i), aggregate_hint[a], AggregateMethodRole) for i, a in enumerate(aggregate): self.aggregate_list.setData(self.aggregate_list.index(i), aggregate_hint[a], AggregateMethodRole) def update_hints(self): for i, var in enumerate(self.group_list): self.hints[var.name, var.var_type] = \ ("group_by", str(self.group_list.data( \ self.group_list.index(i), AggregateMethodRole).toPyObject())) for i, var in enumerate(self.aggregate_list): self.hints[var.name, var.var_type] = \ ("aggregate", str(self.aggregate_list.data( \ self.aggregate_list.index(i), AggregateMethodRole).toPyObject())) def clear(self): """ Clear the widget state. """ self.data = None self.group_list[:] = [] #clear() self.aggregate_list[:] = [] #.clear() self.all_attrs = [] self.hints = {} def get_aggregates_from_hints(self): aggregates = {} for i, v in enumerate(self.aggregate_list): _, hint = self.hints.get((v.name, v.var_type), ("", DEFAULT_METHOD)) aggregates[v] = hint.lower() return aggregates def commit_if(self): if self.auto_commit: self.commit() else: self.state_changed_flag = True def commit(self): self.update_hints() if self.data is not None: group = list(self.group_list) aggregates = self.get_aggregates_from_hints() print aggregates data = utils.group_by(self.data, group, attr_aggregate=aggregates) else: data = None self.send("Data", data) self.state_changed_flag = False