class MemUsageDialog(QDialog): def __init__(self, parent=None, update=True): QDialog.__init__(self, parent=parent) layout = QVBoxLayout() self.tree = QTreeWidget() layout.addWidget(self.tree) self.setLayout(layout) self._mgr = CacheMemoryManager() self._tracked_caches = {} # tree setup code self.tree.setHeaderLabels( ["cache", "memory", "roi", "dtype", "type", "info", "id"]) self._idIndex = self.tree.columnCount() - 1 self.tree.setColumnHidden(self._idIndex, True) self.tree.setSortingEnabled(True) self.tree.clear() self._root = TreeNode() # refresh every x seconds (see showEvent()) self.timer = QTimer(self) if update: self.timer.timeout.connect(self._updateReport) def _updateReport(self): # we keep track of dirty reports so we just have to update the tree # instead of reconstructing it reports = [] for c in self._mgr.getFirstClassCaches(): r = MemInfoNode() c.generateReport(r) reports.append(r) self._root.handleChildrenReports( reports, root=self.tree.invisibleRootItem()) def hideEvent(self, event): self.timer.stop() def showEvent(self, show): # update once so we don't have to wait for initial report self._updateReport() # update every 5 sec. self.timer.start(5*1000)
class MemUsageDialog(QDialog): def __init__(self, parent=None, update=True): QDialog.__init__(self, parent=parent) layout = QVBoxLayout() self.tree = QTreeWidget() layout.addWidget(self.tree) self.setLayout(layout) self._mgr = CacheMemoryManager() self._tracked_caches = {} # tree setup code self.tree.setHeaderLabels( ["cache", "memory", "roi", "dtype", "type", "info", "id"]) self._idIndex = self.tree.columnCount() - 1 self.tree.setColumnHidden(self._idIndex, True) self.tree.setSortingEnabled(True) self.tree.clear() self._root = TreeNode() # refresh every x seconds (see showEvent()) self.timer = QTimer(self) if update: self.timer.timeout.connect(self._updateReport) def _updateReport(self): # we keep track of dirty reports so we just have to update the tree # instead of reconstructing it reports = [] for c in self._mgr.getFirstClassCaches(): r = MemInfoNode() c.generateReport(r) reports.append(r) self._root.handleChildrenReports(reports, root=self.tree.invisibleRootItem()) def hideEvent(self, event): self.timer.stop() def showEvent(self, show): # update once so we don't have to wait for initial report self._updateReport() # update every 5 sec. self.timer.start(5 * 1000)
class OWItemsets(widget.OWWidget): name = 'Frequent Itemsets' description = 'Explore sets of items that frequently appear together.' icon = 'icons/FrequentItemsets.svg' priority = 10 inputs = [("Data", Table, 'set_data')] outputs = [(Output.DATA, Table)] minSupport = settings.Setting(30) maxItemsets = settings.Setting(10000) filterSearch = settings.Setting(True) autoFind = settings.Setting(False) autoSend = settings.Setting(True) filterKeywords = settings.Setting('') filterMinItems = settings.Setting(1) filterMaxItems = settings.Setting(10000) UserAdviceMessages = [ widget.Message( 'Itemset are listed in item-sorted order, i.e. ' 'an itemset containing A and B is only listed once, as ' 'A > B (and not also B > A).', 'itemsets-order', widget.Message.Warning), widget.Message( 'To select all the itemsets that are descendants of ' '(include) some item X (i.e. the whole subtree), you ' 'can fold the subtree at that item and then select it.', 'itemsets-order', widget.Message.Information) ] def __init__(self): self._is_running = False self.isRegexMatch = lambda x: True self.tree = QTreeWidget(self.mainArea, columnCount=2, allColumnsShowFocus=True, alternatingRowColors=True, selectionMode=QTreeWidget.ExtendedSelection, uniformRowHeights=True) self.tree.setHeaderLabels(["Itemsets", "Support", "%"]) self.tree.header().setStretchLastSection(True) self.tree.itemSelectionChanged.connect(self.selectionChanged) self.mainArea.layout().addWidget(self.tree) box = gui.widgetBox(self.controlArea, "Info") self.nItemsets = self.nSelectedExamples = self.nSelectedItemsets = '' gui.label(box, self, "Number of itemsets: %(nItemsets)s") gui.label(box, self, "Selected itemsets: %(nSelectedItemsets)s") gui.label(box, self, "Selected examples: %(nSelectedExamples)s") hbox = gui.widgetBox(box, orientation='horizontal') gui.button(hbox, self, "Expand all", callback=self.tree.expandAll) gui.button(hbox, self, "Collapse all", callback=self.tree.collapseAll) box = gui.widgetBox(self.controlArea, 'Find itemsets') gui.valueSlider(box, self, 'minSupport', values=[.0001, .0005, .001, .005, .01, .05, .1, .5] + list(range(1, 101)), label='Minimal support:', labelFormat="%g%%", callback=lambda: self.find_itemsets()) gui.hSlider(box, self, 'maxItemsets', minValue=10000, maxValue=100000, step=10000, label='Max. number of itemsets:', labelFormat="%d", callback=lambda: self.find_itemsets()) self.button = gui.auto_commit(box, self, 'autoFind', 'Find itemsets', commit=self.find_itemsets) box = gui.widgetBox(self.controlArea, 'Filter itemsets') gui.lineEdit(box, self, 'filterKeywords', 'Contains:', callback=self.filter_change, orientation='horizontal', tooltip='A comma or space-separated list of regular ' 'expressions.') hbox = gui.widgetBox(box, orientation='horizontal') gui.spin(hbox, self, 'filterMinItems', 1, 998, label='Min. items:', callback=self.filter_change) gui.spin(hbox, self, 'filterMaxItems', 2, 999, label='Max. items:', callback=self.filter_change) gui.checkBox(box, self, 'filterSearch', label='Apply these filters in search', tooltip='If checked, the itemsets are filtered according ' 'to these filter conditions already in the search ' 'phase. \nIf unchecked, the only filters applied ' 'during search are the ones above, ' 'and the itemsets are \nfiltered afterwards only for ' 'display, i.e. only the matching itemsets are shown.') gui.rubber(hbox) gui.rubber(self.controlArea) gui.auto_commit(self.controlArea, self, 'autoSend', 'Send selection') self.filter_change() ITEM_DATA_ROLE = Qt.UserRole + 1 def selectionChanged(self): X = self.X mapping = self.onehot_mapping instances = set() where = np.where def whole_subtree(node): yield node for i in range(node.childCount()): yield from whole_subtree(node.child(i)) def itemset(node): while node: yield node.data(0, self.ITEM_DATA_ROLE) node = node.parent() def selection_ranges(node): n_children = node.childCount() if n_children: yield (self.tree.indexFromItem(node.child(0)), self.tree.indexFromItem(node.child(n_children - 1))) for i in range(n_children): yield from selection_ranges(node.child(i)) nSelectedItemsets = 0 item_selection = QItemSelection() for node in self.tree.selectedItems(): nodes = (node, ) if node.isExpanded() else whole_subtree(node) if not node.isExpanded(): for srange in selection_ranges(node): item_selection.select(*srange) for node in nodes: nSelectedItemsets += 1 cols, vals = zip(*(mapping[i] for i in itemset(node))) if issparse(X): rows = (len(cols) == np.bincount( (X[:, cols] != 0).indices, minlength=X.shape[0])).nonzero()[0] else: rows = where((X[:, cols] == vals).all(axis=1))[0] instances.update(rows) self.tree.itemSelectionChanged.disconnect(self.selectionChanged) self.tree.selectionModel().select( item_selection, QItemSelectionModel.Select | QItemSelectionModel.Rows) self.tree.itemSelectionChanged.connect(self.selectionChanged) self.nSelectedExamples = len(instances) self.nSelectedItemsets = nSelectedItemsets self.output = self.data[sorted(instances)] or None self.commit() def commit(self): self.send(Output.DATA, self.output) def filter_change(self): self.warning(9) try: isRegexMatch = self.isRegexMatch = re.compile( '|'.join( i.strip() for i in re.split('(,|\s)+', self.filterKeywords.strip()) if i.strip()), re.IGNORECASE).search except Exception as e: self.warning(9, 'Error in regular expression: {}'.format(e.args[0])) isRegexMatch = self.isRegexMatch = lambda x: True def hide(node, depth, has_kw): if not has_kw: has_kw = isRegexMatch(node.text(0)) hidden = ( sum( hide(node.child(i), depth + 1, has_kw) for i in range(node.childCount())) == node.childCount() if node.childCount() else (not has_kw or not self.filterMinItems <= depth <= self.filterMaxItems)) node.setHidden(hidden) return hidden hide(self.tree.invisibleRootItem(), 0, False) class TreeWidgetItem(QTreeWidgetItem): def data(self, column, role): """Construct lazy tooltips""" if role != Qt.ToolTipRole: return super().data(column, role) tooltip = [] while self: tooltip.append(self.text(0)) self = self.parent() return ' '.join(reversed(tooltip)) def find_itemsets(self): if self.data is None: return if self._is_running: return self._is_running = True data = self.data self.tree.clear() self.tree.setUpdatesEnabled(False) self.tree.blockSignals(True) class ItemDict(dict): def __init__(self, item): self.item = item top = ItemDict(self.tree.invisibleRootItem()) X, mapping = OneHot.encode(data) self.onehot_mapping = mapping ITEM_FMT = '{}' if issparse(data.X) else '{}={}' names = { item: ITEM_FMT.format(var.name, val) for item, var, val in OneHot.decode(mapping.keys(), data, mapping) } nItemsets = 0 filterSearch = self.filterSearch filterMinItems, filterMaxItems = self.filterMinItems, self.filterMaxItems isRegexMatch = self.isRegexMatch # Find itemsets and populate the TreeView with self.progressBar(self.maxItemsets + 1) as progress: for itemset, support in frequent_itemsets(X, self.minSupport / 100): if filterSearch and not filterMinItems <= len( itemset) <= filterMaxItems: continue parent = top first_new_item = None itemset_matches_filter = False for item in sorted(itemset): name = names[item] if filterSearch and not itemset_matches_filter: itemset_matches_filter = isRegexMatch(name) child = parent.get(name) if child is None: try: wi = self.TreeWidgetItem(parent.item, [ name, str(support), '{:.4g}'.format( 100 * support / len(data)) ]) except RuntimeError: # FIXME: When autoFind was in effect and the support # slider was moved, this line excepted with: # RuntimeError: wrapped C/C++ object of type # TreeWidgetItem has been deleted return wi.setData(0, self.ITEM_DATA_ROLE, item) child = parent[name] = ItemDict(wi) if first_new_item is None: first_new_item = (parent, name) parent = child if filterSearch and not itemset_matches_filter: parent, name = first_new_item parent.item.removeChild(parent[name].item) del parent[name].item del parent[name] else: nItemsets += 1 progress.advance() if nItemsets >= self.maxItemsets: break if not filterSearch: self.filter_change() self.nItemsets = nItemsets self.nSelectedItemsets = 0 self.nSelectedExamples = 0 self.tree.expandAll() for i in range(self.tree.columnCount()): self.tree.resizeColumnToContents(i) self.tree.setUpdatesEnabled(True) self.tree.blockSignals(False) self._is_running = False def set_data(self, data): self.data = data is_error = False if data is not None: self.warning(0) self.error(1) self.button.setDisabled(False) self.X = data.X if issparse(data.X): self.X = data.X.tocsc() else: if not data.domain.has_discrete_attributes(): self.error( 1, 'Discrete features required but data has none.') is_error = True self.button.setDisabled(True) elif data.domain.has_continuous_attributes(): self.warning( 0, 'Data has continuous attributes which will be skipped.' ) else: self.output = None self.commit() if self.autoFind and not is_error: self.find_itemsets()
class Shortcuts(preferences.Page): def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton( icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager( win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = list(allactions.keys()) def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelerator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0) def items(self): """Yield all the items in the actions tree.""" def children(item): for i in range(item.childCount()): c = item.child(i) if c.childCount(): for c1 in children(c): yield c1 else: yield c for c in children(self.tree.invisibleRootItem()): yield c def item(self, collection, name): for item in self.items(): if item.collection.name == collection and item.name == name: return item def saveSettings(self): self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts") for item in self.items(): for scheme in self.scheme.schemes(): item.save(scheme) item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def loadSettings(self): self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes") # clear the settings in all the items for item in self.items(): item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def slotSchemeChanged(self): """Called when the Scheme combobox is changed by the user.""" for item in self.items(): item.switchScheme(self.scheme.currentScheme()) def slotCurrentItemChanged(self, item): if isinstance(item, ShortcutItem): self.edit.setText( _("&Edit Shortcut for \"{name}\"").format(name=item.text(0))) self.edit.setEnabled(True) global _lastaction _lastaction = item.name else: self.edit.setText(_("(no shortcut)")) self.edit.setEnabled(False) def import_(self, filename): from . import import_export import_export.importShortcut(filename, self, self.scheme) def export(self, name, filename): from . import import_export try: import_export.exportShortcut(self, self.scheme.currentScheme(), name, filename) except (IOError, OSError) as e: QMessageBox.critical( self, _("Error"), _("Can't write to destination:\n\n{url}\n\n{error}").format( url=filename, error=e.strerror)) def findShortcutConflict(self, shortcut): """Find the possible shortcut conflict and return the conflict name.""" if shortcut: item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return None scheme = self.scheme.currentScheme() for i in self.items(): a = i.action(scheme) if i != item and a.shortcuts(): for s1 in a.shortcuts(): if s1.matches(shortcut) or shortcut.matches(s1): return qutil.removeAccelerator(a.text()) return None def editCurrentItem(self): item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return dlg = ShortcutEditDialog(self, self.findShortcutConflict) scheme = self.scheme.currentScheme() action = item.action(scheme) default = item.defaultShortcuts() or None if dlg.editAction(action, default): shortcuts = action.shortcuts() # check for conflicts conflicting = [] for i in self.items(): if i is not item: for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts): if s1.matches(s2) or s2.matches(s1): conflicting.append(i) if conflicting: for i in conflicting: l = i.shortcuts(scheme) for s1 in list(l): # copy for s2 in shortcuts: if s1.matches(s2) or s2.matches(s1): l.remove(s1) i.setShortcuts(l, scheme) # store the shortcut item.setShortcuts(shortcuts, scheme) self.changed.emit()
class OWItemsets(widget.OWWidget): name = 'Frequent Itemsets' description = 'Explore sets of items that frequently appear together.' icon = 'icons/FrequentItemsets.svg' priority = 10 inputs = [("Data", Table, 'set_data')] outputs = [(Output.DATA, Table)] minSupport = settings.Setting(30) maxItemsets = settings.Setting(10000) filterSearch = settings.Setting(True) autoFind = settings.Setting(False) autoSend = settings.Setting(True) filterKeywords = settings.Setting('') filterMinItems = settings.Setting(1) filterMaxItems = settings.Setting(10000) UserAdviceMessages = [ widget.Message('Itemset are listed in item-sorted order, i.e. ' 'an itemset containing A and B is only listed once, as ' 'A > B (and not also B > A).', 'itemsets-order', widget.Message.Warning), widget.Message('To select all the itemsets that are descendants of ' '(include) some item X (i.e. the whole subtree), you ' 'can fold the subtree at that item and then select it.', 'itemsets-order', widget.Message.Information) ] def __init__(self): self.tree = QTreeWidget(self.mainArea, columnCount=2, allColumnsShowFocus=True, alternatingRowColors=True, selectionMode=QTreeWidget.ExtendedSelection, uniformRowHeights=True) self.tree.setHeaderLabels(["Itemsets", "Support", "%"]) self.tree.header().setStretchLastSection(True) self.tree.itemSelectionChanged.connect(self.selectionChanged) self.mainArea.layout().addWidget(self.tree) box = gui.widgetBox(self.controlArea, "Info") self.nItemsets = self.nSelectedExamples = self.nSelectedItemsets = '' gui.label(box, self, "Number of itemsets: %(nItemsets)s") gui.label(box, self, "Selected itemsets: %(nSelectedItemsets)s") gui.label(box, self, "Selected examples: %(nSelectedExamples)s") hbox = gui.widgetBox(box, orientation='horizontal') gui.button(hbox, self, "Expand all", callback=self.tree.expandAll) gui.button(hbox, self, "Collapse all", callback=self.tree.collapseAll) box = gui.widgetBox(self.controlArea, 'Find itemsets') gui.hSlider(box, self, 'minSupport', minValue=1, maxValue=100, label='Minimal support:', labelFormat="%d%%", callback=lambda: self.find_itemsets()) gui.hSlider(box, self, 'maxItemsets', minValue=10000, maxValue=100000, step=10000, label='Max. number of itemsets:', labelFormat="%d", callback=lambda: self.find_itemsets()) gui.checkBox(box, self, 'filterSearch', label='Apply below filters in search', tooltip='If checked, the itemsets are filtered according ' 'to below filter conditions already in the search ' 'phase. \nIf unchecked, the only filters applied ' 'during search are the ones above, ' 'and the itemsets are \nfiltered afterwards only for ' 'display, i.e. only the matching itemsets are shown.') self.button = gui.auto_commit( box, self, 'autoFind', 'Find itemsets', commit=self.find_itemsets) box = gui.widgetBox(self.controlArea, 'Filter itemsets') gui.lineEdit(box, self, 'filterKeywords', 'Contains:', callback=self.filter_change, orientation='horizontal', tooltip='A comma or space-separated list of regular ' 'expressions.') hbox = gui.widgetBox(box, orientation='horizontal') gui.spin(hbox, self, 'filterMinItems', 1, 998, label='Min. items:', callback=self.filter_change) gui.spin(hbox, self, 'filterMaxItems', 2, 999, label='Max. items:', callback=self.filter_change) gui.rubber(hbox) gui.rubber(self.controlArea) gui.auto_commit(self.controlArea, self, 'autoSend', 'Send selection') self.filter_change() def sendReport(self): self.reportSettings("Itemset statistics", [("Number of itemsets", self.nItemsets), ("Selected itemsets", self.nSelectedItemsets), ("Covered examples", self.nSelectedExamples), ]) self.reportSection("Itemsets") self.reportRaw(OWReport.reportTree(self.tree)) ITEM_DATA_ROLE = Qt.UserRole + 1 def selectionChanged(self): X = self.data.X mapping = self.onehot_mapping instances = set() where = np.where def whole_subtree(node): yield node for i in range(node.childCount()): yield from whole_subtree(node.child(i)) def itemset(node): while node: yield node.data(0, self.ITEM_DATA_ROLE) node = node.parent() def selection_ranges(node): n_children = node.childCount() if n_children: yield (self.tree.indexFromItem(node.child(0)), self.tree.indexFromItem(node.child(n_children - 1))) for i in range(n_children): yield from selection_ranges(node.child(i)) nSelectedItemsets = 0 item_selection = QItemSelection() for node in self.tree.selectedItems(): nodes = (node,) if node.isExpanded() else whole_subtree(node) if not node.isExpanded(): for srange in selection_ranges(node): item_selection.select(*srange) for node in nodes: nSelectedItemsets += 1 cols, vals = zip(*(mapping[i] for i in itemset(node))) instances.update(where((X[:, cols] == vals).all(axis=1))[0]) self.tree.itemSelectionChanged.disconnect(self.selectionChanged) self.tree.selectionModel().select(item_selection, QItemSelectionModel.Select | QItemSelectionModel.Rows) self.tree.itemSelectionChanged.connect(self.selectionChanged) self.nSelectedExamples = len(instances) self.nSelectedItemsets = nSelectedItemsets self.output = self.data[sorted(instances)] or None self.commit() def commit(self): self.send(Output.DATA, self.output) def filter_change(self): isRegexMatch = self.isRegexMatch = re.compile( '|'.join(i.strip() for i in re.split('(,|\s)+', self.filterKeywords.strip()) if i.strip())).search def hide(node, depth, has_kw): if not has_kw: has_kw = isRegexMatch(node.text(0)) hidden = (sum(hide(node.child(i), depth + 1, has_kw) for i in range(node.childCount())) == node.childCount() if node.childCount() else (not has_kw or not self.filterMinItems <= depth <= self.filterMaxItems)) node.setHidden(hidden) return hidden hide(self.tree.invisibleRootItem(), 0, False) class TreeWidgetItem(QTreeWidgetItem): def data(self, column, role): """Construct lazy tooltips""" if role != Qt.ToolTipRole: return super().data(column, role) tooltip = [] while self: tooltip.append(self.text(0)) self = self.parent() return ' '.join(reversed(tooltip)) def find_itemsets(self): if self.data is None: return data = self.data self.tree.clear() self.tree.setUpdatesEnabled(False) self.tree.blockSignals(True) class ItemDict(dict): def __init__(self, item): self.item = item top = ItemDict(self.tree.invisibleRootItem()) X, mapping = OneHot.encode(data) self.onehot_mapping = mapping names = {item: '{}={}'.format(var.name, val) for item, var, val in OneHot.decode(mapping.keys(), data, mapping)} nItemsets = 0 filterSearch = self.filterSearch filterMinItems, filterMaxItems = self.filterMinItems, self.filterMaxItems isRegexMatch = self.isRegexMatch # Find itemsets and populate the TreeView progress = gui.ProgressBar(self, self.maxItemsets + 1) for itemset, support in frequent_itemsets(X, self.minSupport / 100): if filterSearch and not filterMinItems <= len(itemset) <= filterMaxItems: continue parent = top first_new_item = None itemset_matches_filter = False for item in sorted(itemset): name = names[item] if filterSearch and not itemset_matches_filter: itemset_matches_filter = isRegexMatch(name) child = parent.get(name) if child is None: wi = self.TreeWidgetItem(parent.item, [name, str(support), '{:.1f}'.format(100 * support / len(data))]) wi.setData(0, self.ITEM_DATA_ROLE, item) child = parent[name] = ItemDict(wi) if first_new_item is None: first_new_item = (parent, name) parent = child if filterSearch and not itemset_matches_filter: parent, name = first_new_item parent.item.removeChild(parent[name].item) del parent[name].item del parent[name] else: nItemsets += 1 progress.advance() if nItemsets >= self.maxItemsets: break if not filterSearch: self.filter_change() self.nItemsets = nItemsets self.nSelectedItemsets = 0 self.nSelectedExamples = 0 self.tree.expandAll() for i in range(self.tree.columnCount()): self.tree.resizeColumnToContents(i) self.tree.setUpdatesEnabled(True) self.tree.blockSignals(False) progress.finish() def set_data(self, data): self.data = data if data is not None: self.warning(0, 'Data has continuous attributes which will be skipped.' if data.domain.has_continuous_attributes() else None) self.error(1, 'Discrete features required but data has none.' if not data.domain.has_discrete_attributes() else None) self.button.setDisabled(not data.domain.has_discrete_attributes()) if self.autoFind: self.find_itemsets()
class OWGEODatasets(OWWidget): name = "GEO Data Sets" description = DESCRIPTION icon = "../widgets/icons/GEODataSets.svg" priority = PRIORITY inputs = [] outputs = [("Expression Data", Orange.data.Table)] settingsList = [ "outputRows", "mergeSpots", "gdsSelectionStates", "splitterSettings", "currentGds", "autoCommit", "datasetNames" ] outputRows = Setting(True) mergeSpots = Setting(True) gdsSelectionStates = Setting({}) currentGds = Setting(None) datasetNames = Setting({}) splitterSettings = Setting(( b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xea\x00\x00\x00\xd7\x01\x00\x00\x00\x07\x01\x00\x00\x00\x02', b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xb5\x00\x00\x02\x10\x01\x00\x00\x00\x07\x01\x00\x00\x00\x01' )) autoCommit = Setting(False) def __init__(self, parent=None, signalManager=None, name=" GEO Data Sets"): OWWidget.__init__(self, parent, signalManager, name) self.selectionChanged = False self.filterString = "" self.datasetName = "" ## GUI box = gui.widgetBox(self.controlArea, "Info", addSpace=True) self.infoBox = gui.widgetLabel(box, "Initializing\n\n") box = gui.widgetBox(self.controlArea, "Output", addSpace=True) gui.radioButtonsInBox(box, self, "outputRows", ["Genes in rows", "Samples in rows"], "Rows", callback=self.commitIf) gui.checkBox(box, self, "mergeSpots", "Merge spots of same gene", callback=self.commitIf) gui.separator(box) self.nameEdit = gui.lineEdit( box, self, "datasetName", "Data set name", tooltip="Override the default output data set name", callback=self.onNameEdited) self.nameEdit.setPlaceholderText("") if sys.version_info < (3, ): box = gui.widgetBox(self.controlArea, "Commit", addSpace=True) self.commitButton = gui.button(box, self, "Commit", callback=self.commit) cb = gui.checkBox(box, self, "autoCommit", "Commit on any change") gui.setStopper(self, self.commitButton, cb, "selectionChanged", self.commit) else: gui.auto_commit(self.controlArea, self, "autoCommit", "Commit", box="Commit") self.commitIf = self.commit gui.rubber(self.controlArea) gui.widgetLabel(self.mainArea, "Filter") self.filterLineEdit = QLineEdit(textChanged=self.filter) self.completer = TokenListCompleter(self, caseSensitivity=Qt.CaseInsensitive) self.filterLineEdit.setCompleter(self.completer) self.mainArea.layout().addWidget(self.filterLineEdit) splitter = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(splitter) self.treeWidget = QTreeView(splitter) self.treeWidget.setSelectionMode(QTreeView.SingleSelection) self.treeWidget.setRootIsDecorated(False) self.treeWidget.setSortingEnabled(True) self.treeWidget.setAlternatingRowColors(True) self.treeWidget.setUniformRowHeights(True) self.treeWidget.setEditTriggers(QTreeView.NoEditTriggers) linkdelegate = LinkStyledItemDelegate(self.treeWidget) self.treeWidget.setItemDelegateForColumn(1, linkdelegate) self.treeWidget.setItemDelegateForColumn(8, linkdelegate) self.treeWidget.setItemDelegateForColumn( 0, gui.IndicatorItemDelegate(self.treeWidget, role=Qt.DisplayRole)) proxyModel = MySortFilterProxyModel(self.treeWidget) self.treeWidget.setModel(proxyModel) self.treeWidget.selectionModel().selectionChanged.connect( self.updateSelection) self.treeWidget.viewport().setMouseTracking(True) splitterH = QSplitter(Qt.Horizontal, splitter) box = gui.widgetBox(splitterH, "Description") self.infoGDS = gui.widgetLabel(box, "") self.infoGDS.setWordWrap(True) gui.rubber(box) box = gui.widgetBox(splitterH, "Sample Annotations") self.annotationsTree = QTreeWidget(box) self.annotationsTree.setHeaderLabels( ["Type (Sample annotations)", "Sample count"]) self.annotationsTree.setRootIsDecorated(True) box.layout().addWidget(self.annotationsTree) self.annotationsTree.itemChanged.connect( self.annotationSelectionChanged) self._annotationsUpdating = False self.splitters = splitter, splitterH for sp, setting in zip(self.splitters, self.splitterSettings): sp.splitterMoved.connect(self.splitterMoved) sp.restoreState(setting) self.searchKeys = [ "dataset_id", "title", "platform_organism", "description" ] self.gds = [] self.gds_info = None self.resize(1000, 600) self.setBlocking(True) self.setEnabled(False) self.progressBarInit() self._executor = ThreadExecutor() func = partial(get_gds_model, methodinvoke(self, "_setProgress", (float, ))) self._inittask = Task(function=func) self._inittask.finished.connect(self._initializemodel) self._executor.submit(self._inittask) self._datatask = None @Slot(float) def _setProgress(self, value): self.progressBarValue = value def _initializemodel(self): assert self.thread() is QThread.currentThread() model, self.gds_info, self.gds = self._inittask.result() model.setParent(self) proxy = self.treeWidget.model() proxy.setFilterKeyColumn(0) proxy.setFilterRole(TextFilterRole) proxy.setFilterCaseSensitivity(False) proxy.setFilterFixedString(self.filterString) proxy.setSourceModel(model) proxy.sort(0, Qt.DescendingOrder) self.progressBarFinished() self.setBlocking(False) self.setEnabled(True) filter_items = " ".join(gds[key] for gds in self.gds for key in self.searchKeys) tr_chars = ",.:;!?(){}[]_-+\\|/%#@$^&*<>~`" tr_table = str.maketrans(tr_chars, " " * len(tr_chars)) filter_items = filter_items.translate(tr_table) filter_items = sorted(set(filter_items.split(" "))) filter_items = [item for item in filter_items if len(item) > 3] self.completer.setTokenList(filter_items) if self.currentGds: current_id = self.currentGds["dataset_id"] gdss = [(i, qunpack(proxy.data(proxy.index(i, 1), Qt.DisplayRole))) for i in range(proxy.rowCount())] current = [i for i, data in gdss if data and data == current_id] if current: current_index = proxy.index(current[0], 0) self.treeWidget.selectionModel().select( current_index, QItemSelectionModel.Select | QItemSelectionModel.Rows) self.treeWidget.scrollTo(current_index, QTreeView.PositionAtCenter) for i in range(8): self.treeWidget.resizeColumnToContents(i) self.treeWidget.setColumnWidth( 1, min(self.treeWidget.columnWidth(1), 300)) self.treeWidget.setColumnWidth( 2, min(self.treeWidget.columnWidth(2), 200)) self.updateInfo() def updateInfo(self): gds_info = self.gds_info text = ("%i datasets\n%i datasets cached\n" % (len(gds_info), len(glob.glob(serverfiles.localpath("GEO") + "/GDS*")))) filtered = self.treeWidget.model().rowCount() if len(self.gds) != filtered: text += ("%i after filtering") % filtered self.infoBox.setText(text) def updateSelection(self, *args): current = self.treeWidget.selectedIndexes() mapToSource = self.treeWidget.model().mapToSource current = [mapToSource(index).row() for index in current] if current: self.currentGds = self.gds[current[0]] self.setAnnotations(self.currentGds) self.infoGDS.setText(self.currentGds.get("description", "")) self.nameEdit.setPlaceholderText(self.currentGds["title"]) self.datasetName = \ self.datasetNames.get(self.currentGds["dataset_id"], "") else: self.currentGds = None self.nameEdit.setPlaceholderText("") self.datasetName = "" self.commitIf() def setAnnotations(self, gds): self._annotationsUpdating = True self.annotationsTree.clear() annotations = defaultdict(set) subsetscount = {} for desc in gds["subsets"]: annotations[desc["type"]].add(desc["description"]) subsetscount[desc["description"]] = str(len(desc["sample_id"])) for type, subsets in annotations.items(): key = (gds["dataset_id"], type) subsetItem = QTreeWidgetItem(self.annotationsTree, [type]) subsetItem.setFlags(subsetItem.flags() | Qt.ItemIsUserCheckable | Qt.ItemIsTristate) subsetItem.setCheckState( 0, self.gdsSelectionStates.get(key, Qt.Checked)) subsetItem.key = key for subset in subsets: key = (gds["dataset_id"], type, subset) item = QTreeWidgetItem( subsetItem, [subset, subsetscount.get(subset, "")]) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState( 0, self.gdsSelectionStates.get(key, Qt.Checked)) item.key = key self._annotationsUpdating = False self.annotationsTree.expandAll() for i in range(self.annotationsTree.columnCount()): self.annotationsTree.resizeColumnToContents(i) def annotationSelectionChanged(self, item, column): if self._annotationsUpdating: return for i in range(self.annotationsTree.topLevelItemCount()): item = self.annotationsTree.topLevelItem(i) self.gdsSelectionStates[item.key] = item.checkState(0) for j in range(item.childCount()): child = item.child(j) self.gdsSelectionStates[child.key] = child.checkState(0) def filter(self): filter_string = unicode(self.filterLineEdit.text()) proxyModel = self.treeWidget.model() if proxyModel: strings = filter_string.lower().strip().split() proxyModel.setFilterFixedStrings(strings) self.updateInfo() def selectedSamples(self): """ Return the currently selected sample annotations. The return value is a list of selected (sample type, sample value) tuples. .. note:: if some Sample annotation type has no selected values. this method will return all values for it. """ samples = [] unused_types = [] used_types = [] for stype in childiter(self.annotationsTree.invisibleRootItem()): selected_values = [] all_values = [] for sval in childiter(stype): value = (str(stype.text(0)), str(sval.text(0))) if self.gdsSelectionStates.get(sval.key, True): selected_values.append(value) all_values.append(value) if selected_values: samples.extend(selected_values) used_types.append(str(stype.text(0))) else: # If no sample of sample type is selected we don't filter # on it. samples.extend(all_values) unused_types.append(str(stype.text(0))) return samples, used_types def commitIf(self): if self.autoCommit: self.commit() else: self.selectionChanged = True @Slot(int, int) def progressCompleted(self, value, total): if total > 0: self.progressBarSet(100. * value / total, processEvents=False) else: pass # TODO: report 'indeterminate progress' def commit(self): if self.currentGds: self.error(0) sample_type = None self.progressBarInit(processEvents=None) _, groups = self.selectedSamples() if len(groups) == 1 and self.outputRows: sample_type = groups[0] self.setEnabled(False) self.setBlocking(True) progress = methodinvoke(self, "progressCompleted", (int, int)) def get_data(gds_id, report_genes, transpose, sample_type, title): gds_ensure_downloaded(gds_id, progress) gds = geo.GDS(gds_id) data = gds.getdata(report_genes=report_genes, transpose=transpose, sample_type=sample_type) data.name = title return data get_data = partial(get_data, self.currentGds["dataset_id"], report_genes=self.mergeSpots, transpose=self.outputRows, sample_type=sample_type, title=self.datasetName or self.currentGds["title"]) self._datatask = Task(function=get_data) self._datatask.finished.connect(self._on_dataready) self._executor.submit(self._datatask) def _on_dataready(self): self.setEnabled(True) self.setBlocking(False) self.progressBarFinished(processEvents=False) try: data = self._datatask.result() except urlrequest.URLError as error: self.error(0, ("Error while connecting to the NCBI ftp server! " "'%s'" % error)) sys.excepthook(type(error), error, getattr(error, "__traceback__")) return finally: self._datatask = None data_name = data.name samples, _ = self.selectedSamples() self.warning(0) message = None if self.outputRows: def samplesinst(ex): out = [] for meta in data.domain.metas: out.append((meta.name, ex[meta].value)) if data.domain.class_var.name != 'class': out.append((data.domain.class_var.name, ex[data.domain.class_var].value)) return out samples = set(samples) mask = [samples.issuperset(samplesinst(ex)) for ex in data] data = data[numpy.array(mask, dtype=bool)] if len(data) == 0: message = "No samples with selected sample annotations." else: samples = set(samples) domain = Orange.data.Domain([ attr for attr in data.domain.attributes if samples.issuperset(attr.attributes.items()) ], data.domain.class_var, data.domain.metas) # domain.addmetas(data.domain.getmetas()) if len(domain.attributes) == 0: message = "No samples with selected sample annotations." stypes = set(s[0] for s in samples) for attr in domain.attributes: attr.attributes = dict( (key, value) for key, value in attr.attributes.items() if key in stypes) data = Orange.data.Table(domain, data) if message is not None: self.warning(0, message) data_hints.set_hint(data, "taxid", self.currentGds.get("taxid", ""), 10.0) data_hints.set_hint(data, "genesinrows", self.outputRows, 10.0) data.name = data_name self.send("Expression Data", data) model = self.treeWidget.model().sourceModel() row = self.gds.index(self.currentGds) model.setData(model.index(row, 0), " ", Qt.DisplayRole) self.updateInfo() self.selectionChanged = False def splitterMoved(self, *args): self.splitterSettings = [ bytes(sp.saveState()) for sp in self.splitters ] def send_report(self): self.report_items("GEO Dataset", [("ID", self.currentGds['dataset_id']), ("Title", self.currentGds['title']), ("Organism", self.currentGds['sample_organism'])]) self.report_items("Data", [("Samples", self.currentGds['sample_count']), ("Features", self.currentGds['feature_count']), ("Genes", self.currentGds['gene_count'])]) self.report_name("Sample annotations") subsets = defaultdict(list) for subset in self.currentGds['subsets']: subsets[subset['type']].append( (subset['description'], len(subset['sample_id']))) self.report_html += "<ul>" for type in subsets: self.report_html += "<b>" + type + ":</b></br>" for desc, count in subsets[type]: self.report_html += 9 * " " + "<b>{}:</b> {}</br>".format( desc, count) self.report_html += "</ul>" def onDeleteWidget(self): if self._inittask: self._inittask.future().cancel() self._inittask.finished.disconnect(self._initializemodel) if self._datatask: self._datatask.future().cancel() self._datatask.finished.disconnect(self._on_dataready) self._executor.shutdown(wait=False) super(OWGEODatasets, self).onDeleteWidget() def onNameEdited(self): if self.currentGds: gds_id = self.currentGds["dataset_id"] self.datasetNames[gds_id] = unicode(self.nameEdit.text()) self.commitIf()
def __init__(self, context, parent=None): """ :type context: segyviewlib.SliceViewContext :type parent: QObject """ QWidget.__init__(self, parent, Qt.WindowStaysOnTopHint | Qt.Window) self.setVisible(False) self._context = context self._context.context_changed.connect(self._settings_changed) self._context.data_changed.connect(self._settings_changed) self._context.data_source_changed.connect(self._settings_changed) f_layout = QFormLayout() self._iline_count = QLabel("") self._xline_count = QLabel("") self._offset_count = QLabel("") self._sample_count = QLabel("") self._minimum_value = QLabel("") self._maximum_value = QLabel("") f_layout.addRow("Inline Count:", self._iline_count) f_layout.addRow("Crossline Count:", self._xline_count) f_layout.addRow("Offset Count:", self._offset_count) f_layout.addRow("Sample Count:", self._sample_count) f_layout.addRow("Minimum Value:", self._minimum_value) f_layout.addRow("Maximum Value:", self._maximum_value) # iline self._il_ctrl = IndexController( parent=self, context=self._context, slice_direction_index_source=SliceDirection.inline) self._il_ctrl.index_changed.connect( self._index_changed_fn(SliceDirection.inline)) self._il_ctrl.min_max_changed.connect(self.iline_limits_changed) # xline self._xl_ctrl = IndexController( parent=self, context=self._context, slice_direction_index_source=SliceDirection.crossline) self._xl_ctrl.index_changed.connect( self._index_changed_fn(SliceDirection.crossline)) self._xl_ctrl.min_max_changed.connect(self.xline_limits_changed) # depth self._depth_ctrl = IndexController( parent=self, context=self._context, slice_direction_index_source=SliceDirection.depth) self._depth_ctrl.index_changed.connect( self._index_changed_fn(SliceDirection.depth)) self._depth_ctrl.min_max_changed.connect(self.depth_limits_changed) # sample self._sample_ctrl = SampleScaleController(self) self._sample_ctrl.min_max_changed.connect(self.sample_limits_changed) self._symmetric_scale = QCheckBox() self._symmetric_scale.toggled.connect( self._context.set_symmetric_scale) self._samples_unit = QComboBox() self._samples_unit.addItems(['Time (ms)', 'Depth (m)']) self._samples_unit.currentIndexChanged[str].connect(self.samples_unit) # view self._view_label = QLabel("") self._view_label.setDisabled(True) self._indicator_visibility = QCheckBox() self._indicator_visibility.toggled.connect( self._context.show_indicators) self._indicator_visibility.toggled.connect( lambda: self._set_view_label(self._indicator_visibility.isChecked( ))) self._interpolation_combo = QComboBox() self._interpolations_names = ['nearest', 'catrom', 'sinc'] self._interpolation_combo.addItems(self._interpolations_names) self._interpolation_combo.currentIndexChanged.connect( self._interpolation_changed) # plot export settings if self._context._has_data: self._plt_settings_wdgt = PlotExportSettingsWidget( self, parent._slice_view_widget, self._context) # define tree layout tree_def = { "": [ { "Inline": [{ "set_expanded": True }, { "": self._align(self._il_ctrl.current_index_label) }, { "Inline:": self._align(self._il_ctrl.index_widget) }, { "Minimum:": self._align(self._il_ctrl.min_spinbox, self._il_ctrl.min_checkbox) }, { "Maximum:": self._align(self._il_ctrl.max_spinbox, self._il_ctrl.max_checkbox) }] }, { "Crossline": [{ "set_expanded": True }, { "": self._align(self._xl_ctrl.current_index_label) }, { "Crossline:": self._align(self._xl_ctrl.index_widget) }, { "Minimum:": self._align(self._xl_ctrl.min_spinbox, self._xl_ctrl.min_checkbox) }, { "Maximum:": self._align(self._xl_ctrl.max_spinbox, self._xl_ctrl.max_checkbox) }] }, { "Depth": [{ "set_expanded": True }, { "": self._align(self._depth_ctrl.current_index_label) }, { "Depth:": self._align(self._depth_ctrl.index_widget) }, { "Minimum:": self._align(self._depth_ctrl.min_spinbox, self._depth_ctrl.min_checkbox) }, { "Maximum:": self._align(self._depth_ctrl.max_spinbox, self._depth_ctrl.max_checkbox) }, { "Type": self._align(self._samples_unit) }] }, { "Sample": [{ "Custom min.:": self._align(self._sample_ctrl.min_spinbox, self._sample_ctrl.min_checkbox) }, { "Custom max.:": self._align(self._sample_ctrl.max_spinbox, self._sample_ctrl.max_checkbox) }, { "Symmetric scale:": self._align(self._symmetric_scale) }] }, { "View": [{ "": self._align(self._view_label) }, { "Show Indicators:": self._align(self._indicator_visibility) }, { "Interpolation Type:": self._align(self._interpolation_combo) }] }, ] } if self._context._has_data: tree_def[''].append({ "Plot export dimensions": [{ "": self._align(self._plt_settings_wdgt.label) }, { "Fixed size": self._align(self._plt_settings_wdgt.checkbox) }, { "Width:": self._align(self._plt_settings_wdgt.width_spinbox) }, { "Height:": self._align(self._plt_settings_wdgt.height_spinbox) }, { "Units:": self._align(self._plt_settings_wdgt.units_combobox) }] }) # setup the menu/navigation tree widget tre = QTreeWidget(self) tre.setHeaderHidden(True) tre.setColumnCount(2) tre.setColumnWidth(0, 140) tre.setColumnWidth(1, 180) self._build_tree(tre, tree_def, tre.invisibleRootItem()) # layout vertical_layout = QVBoxLayout() button_layout = QHBoxLayout() button_layout.setContentsMargins(0, 0, 0, 0) close_button = QPushButton("Close") close_button.clicked.connect(self.close) button_layout.addStretch() button_layout.addWidget(close_button) vertical_layout.addLayout(f_layout, 0) vertical_layout.addStretch() vertical_layout.addWidget(tre, 1) vertical_layout.addStretch() vertical_layout.addLayout(button_layout, 0) self.setLayout(vertical_layout) self.setMinimumSize(390, 740)
class StepKwMultiClassifications(WizardStep, FORM_CLASS): """InaSAFE Wizard Step Multi Classifications.""" def __init__(self, parent=None): """Constructor for the tab. :param parent: widget to use as parent (Wizard Dialog). :type parent: QWidget """ WizardStep.__init__(self, parent) self.exposures = [] self.exposure_labels = [] self.exposure_combo_boxes = [] self.exposure_edit_buttons = [] self.mode = CHOOSE_MODE self.layer_purpose = None self.layer_mode = None # Store the current representative state of the UI. # self.classifications = {} self.value_maps = {} self.thresholds = {} # Temporary attributes self.threshold_classes = OrderedDict() self.active_exposure = None self.list_unique_values = None self.tree_mapping_widget = None # GUI, good for testing self.save_button = None # Has default threshold # Trick for EQ raster for population #3853 self.use_default_thresholds = False # Index of the special case exposure classification self.special_case_index = None def is_ready_to_next_step(self): """Check if the step is complete. :returns: True if new step may be enabled. :rtype: bool """ # Still editing if self.mode == EDIT_MODE: return False for combo_box in self.exposure_combo_boxes: # Enable if there is one that has classification if combo_box.currentIndex() > 0: return True # Trick for EQ raster for population #3853 if self.use_default_thresholds: return True return False def get_next_step(self): """Find the proper step when user clicks the Next button. :returns: The step to be switched to. :rtype: WizardStep instance or None """ if self.layer_purpose != layer_purpose_aggregation: subcategory = self.parent.step_kw_subcategory.\ selected_subcategory() else: subcategory = {'key': None} if is_raster_layer(self.parent.layer): return self.parent.step_kw_source # Check if it can go to inasafe field step inasafe_fields = get_non_compulsory_fields( self.layer_purpose['key'], subcategory['key']) if not skip_inasafe_field(self.parent.layer, inasafe_fields): return self.parent.step_kw_inasafe_fields # Check if it can go to inasafe default field step default_inasafe_fields = get_fields( self.layer_purpose['key'], subcategory['key'], replace_null=True, in_group=False ) if default_inasafe_fields: return self.parent.step_kw_default_inasafe_fields # Any other case return self.parent.step_kw_source def set_wizard_step_description(self): """Set the text for description.""" subcategory = self.parent.step_kw_subcategory.selected_subcategory() field = self.parent.step_kw_field.selected_fields() is_raster = is_raster_layer(self.parent.layer) if is_raster: if self.layer_mode == layer_mode_continuous: text_label = multiple_continuous_hazard_classifications_raster else: text_label = multiple_classified_hazard_classifications_raster # noinspection PyAugmentAssignment text_label = text_label % ( subcategory['name'], self.layer_purpose['name']) else: if self.layer_mode == layer_mode_continuous: text_label = multiple_continuous_hazard_classifications_vector else: text_label = multiple_classified_hazard_classifications_vector # noinspection PyAugmentAssignment text_label = text_label % ( subcategory['name'], self.layer_purpose['name'], field) self.multi_classifications_label.setText(text_label) def setup_left_panel(self): """Setup the UI for left panel. Generate all exposure, combobox, and edit button. """ hazard = self.parent.step_kw_subcategory.selected_subcategory() left_panel_heading = QLabel(tr('Classifications')) left_panel_heading.setFont(big_font) self.left_layout.addWidget(left_panel_heading) inner_left_layout = QGridLayout() row = 0 for exposure in exposure_all: special_case = False # Filter out unsupported exposure for the hazard if exposure in hazard['disabled_exposures']: # Remove from the storage if the exposure is disabled if self.layer_mode == layer_mode_continuous: if exposure['key'] in self.thresholds: self.thresholds.pop(exposure['key']) else: if exposure['key'] in self.value_maps: self.value_maps.pop(exposure['key']) continue # Trick for EQ raster for population #3853 if exposure == exposure_population and hazard == hazard_earthquake: if is_raster_layer(self.parent.layer): if self.layer_mode == layer_mode_continuous: self.use_default_thresholds = True special_case = True # Set classification for EQ Raster for Population self.thresholds[exposure_population['key']] = { earthquake_mmi_scale['key']: { 'classes': default_classification_thresholds( earthquake_mmi_scale), 'active': True } } # Add label # Hazard on Exposure Classifications label = tr( '{hazard_name} on {exposure_name} Classifications').format( hazard_name=hazard['name'], exposure_name=exposure['name'] ) exposure_label = QLabel(label) # Add combo box exposure_combo_box = QComboBox() hazard_classifications = hazard.get('classifications') exposure_combo_box.addItem(tr('No classifications')) exposure_combo_box.setItemData( 0, None, Qt.UserRole) current_index = 0 i = 0 # Iterate through all available hazard classifications for hazard_classification in hazard_classifications: # Skip if the classification is not for the exposure if 'exposures' in hazard_classification: if exposure not in hazard_classification['exposures']: continue exposure_combo_box.addItem(hazard_classification['name']) exposure_combo_box.setItemData( i + 1, hazard_classification, Qt.UserRole) if self.layer_mode == layer_mode_continuous: current_hazard_classifications = self.thresholds.get( exposure['key']) else: current_hazard_classifications = self.value_maps.get( exposure['key']) if current_hazard_classifications: current_hazard_classification = \ current_hazard_classifications.get( hazard_classification['key']) if current_hazard_classification: is_active = current_hazard_classification.get('active') if is_active: current_index = i + 1 i += 1 # Set current classification exposure_combo_box.setCurrentIndex(current_index) # Add edit button exposure_edit_button = QPushButton(tr('Edit')) # For special case. Raster EQ on Population. if special_case: mmi_index = exposure_combo_box.findText( earthquake_mmi_scale['name']) exposure_combo_box.setCurrentIndex(mmi_index) exposure_combo_box.setEnabled(False) exposure_edit_button.setEnabled(False) tool_tip_message = tr( 'InaSAFE use default classification for Raster Earthquake ' 'hazard on population.') exposure_label.setToolTip(tool_tip_message) exposure_combo_box.setToolTip(tool_tip_message) exposure_edit_button.setToolTip(tool_tip_message) else: if current_index == 0: # Disable if there is no classification chosen. exposure_edit_button.setEnabled(False) exposure_edit_button.clicked.connect( partial(self.edit_button_clicked, edit_button=exposure_edit_button, exposure_combo_box=exposure_combo_box, exposure=exposure)) exposure_combo_box.currentIndexChanged.connect( partial( self.classifications_combo_box_changed, exposure=exposure, exposure_combo_box=exposure_combo_box, edit_button=exposure_edit_button)) # Arrange in layout inner_left_layout.addWidget(exposure_label, row, 0) inner_left_layout.addWidget(exposure_combo_box, row, 1) inner_left_layout.addWidget(exposure_edit_button, row, 2) # Adding to step's attribute self.exposures.append(exposure) self.exposure_combo_boxes.append(exposure_combo_box) self.exposure_edit_buttons.append(exposure_edit_button) self.exposure_labels.append(label) if special_case: self.special_case_index = len(self.exposures) - 1 row += 1 self.left_layout.addLayout(inner_left_layout) # To push the inner_left_layout up self.left_layout.addStretch(1) # noinspection PyUnusedLocal def edit_button_clicked(self, edit_button, exposure_combo_box, exposure): """Method to handle when an edit button is clicked. :param edit_button: The edit button. :type edit_button: QPushButton :param exposure_combo_box: The combo box of the exposure, contains list of classifications. :type exposure_combo_box: QComboBox :param exposure: Exposure definition. :type exposure: dict """ # Note(IS): Do not change the text of edit button for now until we # have better behaviour. classification = self.get_classification(exposure_combo_box) if self.mode == CHOOSE_MODE: # Change mode self.mode = EDIT_MODE # Set active exposure self.active_exposure = exposure # Disable all edit button for exposure_edit_button in self.exposure_edit_buttons: exposure_edit_button.setEnabled(False) # Except one that was clicked # edit_button.setEnabled(True) # Disable all combo box for exposure_combo_box in self.exposure_combo_boxes: exposure_combo_box.setEnabled(False) # Change the edit button to cancel # edit_button.setText(tr('Cancel')) # Clear right panel clear_layout(self.right_layout) # Show edit threshold or value mapping if self.layer_mode == layer_mode_continuous: self.setup_thresholds_panel(classification) else: self.setup_value_mapping_panels(classification) self.add_buttons(classification) elif self.mode == EDIT_MODE: # Behave the same as cancel button clicked. self.cancel_button_clicked() self.parent.pbnNext.setEnabled(self.is_ready_to_next_step()) def show_current_state(self): """Setup the UI for QTextEdit to show the current state.""" right_panel_heading = QLabel(tr('Status')) right_panel_heading.setFont(big_font) right_panel_heading.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Maximum) self.right_layout.addWidget(right_panel_heading) message = m.Message() if self.layer_mode == layer_mode_continuous: title = tr('Thresholds') else: title = tr('Value maps') message.add(m.Heading(title, **INFO_STYLE)) for i in range(len(self.exposures)): message.add(m.Text(self.exposure_labels[i])) classification = self.get_classification( self.exposure_combo_boxes[i]) if self.layer_mode == layer_mode_continuous: thresholds = self.thresholds.get(self.exposures[i]['key']) if not thresholds or not classification: message.add(m.Paragraph(tr('No classifications set.'))) continue table = m.Table( style_class='table table-condensed table-striped') header = m.Row() header.add(m.Cell(tr('Class name'))) header.add(m.Cell(tr('Minimum'))) header.add(m.Cell(tr('Maximum'))) table.add(header) classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda k: k['value']) for the_class in classes: threshold = thresholds[classification['key']]['classes'][ the_class['key']] row = m.Row() row.add(m.Cell(the_class['name'])) row.add(m.Cell(threshold[0])) row.add(m.Cell(threshold[1])) table.add(row) else: value_maps = self.value_maps.get(self.exposures[i]['key']) if not value_maps or not classification: message.add(m.Paragraph(tr('No classifications set.'))) continue table = m.Table( style_class='table table-condensed table-striped') header = m.Row() header.add(m.Cell(tr('Class name'))) header.add(m.Cell(tr('Value'))) table.add(header) classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda k: k['value']) for the_class in classes: value_map = value_maps[classification['key']][ 'classes'].get(the_class['key'], []) row = m.Row() row.add(m.Cell(the_class['name'])) row.add(m.Cell(', '.join([str(v) for v in value_map]))) table.add(row) message.add(table) # status_text_edit = QTextBrowser(None) status_text_edit = QWebView(None) status_text_edit.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Ignored) status_text_edit.page().mainFrame().setScrollBarPolicy( Qt.Horizontal, Qt.ScrollBarAlwaysOff) html_string = html_header() + message.to_html() + html_footer() status_text_edit.setHtml(html_string) self.right_layout.addWidget(status_text_edit) def set_widgets(self): """Set widgets on the Multi classification step.""" self.clear() self.layer_mode = self.parent.step_kw_layermode.selected_layermode() self.layer_purpose = self.parent.step_kw_purpose.selected_purpose() self.set_current_state() # Set the step description self.set_wizard_step_description() # Set the left panel self.setup_left_panel() # Set the right panel, for the beginning show the viewer self.show_current_state() def clear(self): """Clear current state.""" self.exposures = [] self.exposure_labels = [] self.exposure_combo_boxes = [] self.exposure_edit_buttons = [] self.mode = CHOOSE_MODE self.layer_purpose = None self.layer_mode = None self.special_case_index = None self.value_maps = {} self.thresholds = {} # Temporary attributes self.threshold_classes = OrderedDict() self.active_exposure = None self.list_unique_values = None self.tree_mapping_widget = None clear_layout(self.left_layout) clear_layout(self.right_layout) def get_current_state(self): """Obtain current classification and value map / threshold.""" def clean_state(dictionary): """Clean dictionary from bad value. :param dictionary: Dictionary of value maps or thresholds. :type dictionary: dict :returns: Clean state. :rtype: dict """ clean_dictionary = { k: v for k, v in dictionary.items() if isinstance(v, dict)} return clean_dictionary if self.layer_mode == layer_mode_continuous: output = {'thresholds': clean_state(self.thresholds)} key = 'thresholds' else: output = {'value_maps': clean_state(self.value_maps)} key = 'value_maps' # Clean non existing hazard class key empty_exposure_classifications = [] for the_exposure, the_hazard_classifications in output[key].items(): for the_hazard_classification in the_hazard_classifications.\ keys(): invalid_classifications = [] if not definition(the_hazard_classification): invalid_classifications.append( the_hazard_classification) for invalid_classification in invalid_classifications: the_hazard_classifications.pop(invalid_classification) if not the_hazard_classifications: empty_exposure_classifications.append(the_exposure) for empty_exposure_classification in empty_exposure_classifications: output[key].pop(empty_exposure_classification) return output @staticmethod def get_classification(combo_box): """Helper to obtain the classification from a combo box. :param combo_box: A classification combo box. :type combo_box: QComboBox. :returns: Classification definitions. :rtype: dict """ return combo_box.itemData(combo_box.currentIndex(), Qt.UserRole) def setup_thresholds_panel(self, classification): """Setup threshold panel in the right panel. :param classification: Classification definition. :type classification: dict """ # Set text in the label layer_purpose = self.parent.step_kw_purpose.selected_purpose() layer_subcategory = self.parent.step_kw_subcategory.\ selected_subcategory() if is_raster_layer(self.parent.layer): statistics = self.parent.layer.dataProvider().bandStatistics( 1, QgsRasterBandStats.All, self.parent.layer.extent(), 0) description_text = continuous_raster_question % ( layer_purpose['name'], layer_subcategory['name'], classification['name'], statistics.minimumValue, statistics.maximumValue) else: field_name = self.parent.step_kw_field.selected_fields() field_index = self.parent.layer.fieldNameIndex(field_name) min_value_layer = self.parent.layer.minimumValue(field_index) max_value_layer = self.parent.layer.maximumValue(field_index) description_text = continuous_vector_question % ( layer_purpose['name'], layer_subcategory['name'], field_name, classification['name'], min_value_layer, max_value_layer) # Set description description_label = QLabel(description_text) description_label.setWordWrap(True) self.right_layout.addWidget(description_label) if self.thresholds: thresholds = self.thresholds else: thresholds = self.parent.get_existing_keyword('thresholds') selected_unit = self.parent.step_kw_unit.selected_unit()['key'] self.threshold_classes = OrderedDict() classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda the_key: the_key['value']) grid_layout_thresholds = QGridLayout() for i, the_class in enumerate(classes): class_layout = QHBoxLayout() # Class label class_label = QLabel(the_class['name']) # Min label min_label = QLabel(tr('Min >')) # Min value as double spin min_value_input = QDoubleSpinBox() # TODO(IS) We can set the min and max depends on the unit, later min_value_input.setMinimum(0) min_value_input.setMaximum(999999) if thresholds.get(self.active_exposure['key']): exposure_thresholds = thresholds.get( self.active_exposure['key']) if exposure_thresholds.get(classification['key']): exposure_thresholds_classifications = exposure_thresholds\ .get(classification['key']) min_value_input.setValue( exposure_thresholds_classifications['classes'][ the_class['key']][0]) else: default_min = the_class['numeric_default_min'] if isinstance(default_min, dict): default_min = the_class[ 'numeric_default_min'][selected_unit] min_value_input.setValue(default_min) else: default_min = the_class['numeric_default_min'] if isinstance(default_min, dict): default_min = the_class[ 'numeric_default_min'][selected_unit] min_value_input.setValue(default_min) min_value_input.setSingleStep(0.1) # Max label max_label = QLabel(tr('Max <=')) # Max value as double spin max_value_input = QDoubleSpinBox() # TODO(IS) We can set the min and max depends on the unit, later max_value_input.setMinimum(0) max_value_input.setMaximum(999999) if thresholds.get(self.active_exposure['key']): exposure_thresholds = thresholds.get( self.active_exposure['key']) if exposure_thresholds.get(classification['key']): exposure_thresholds_classifications = exposure_thresholds \ .get(classification['key']) max_value_input.setValue( exposure_thresholds_classifications['classes'][ the_class['key']][1]) else: default_max = the_class['numeric_default_max'] if isinstance(default_max, dict): default_max = the_class[ 'numeric_default_max'][selected_unit] max_value_input.setValue(default_max) else: default_max = the_class['numeric_default_max'] if isinstance(default_max, dict): default_max = the_class[ 'numeric_default_max'][selected_unit] max_value_input.setValue(default_max) max_value_input.setSingleStep(0.1) # Add to class_layout class_layout.addWidget(min_label) class_layout.addWidget(min_value_input) class_layout.addWidget(max_label) class_layout.addWidget(max_value_input) class_layout.setStretch(0, 1) class_layout.setStretch(1, 2) class_layout.setStretch(2, 1) class_layout.setStretch(3, 2) # Add to grid_layout grid_layout_thresholds.addWidget(class_label, i, 0) grid_layout_thresholds.addLayout(class_layout, i, 1) self.threshold_classes[the_class['key']] = [ min_value_input, max_value_input] grid_layout_thresholds.setColumnStretch(0, 1) grid_layout_thresholds.setColumnStretch(0, 2) def min_max_changed(double_spin_index, mode): """Slot when min or max value change. :param double_spin_index: The index of the double spin. :type double_spin_index: int :param mode: The flag to indicate the min or max value. :type mode: int """ if mode == MAX_VALUE_MODE: current_max_value = self.threshold_classes.values()[ double_spin_index][1] target_min_value = self.threshold_classes.values()[ double_spin_index + 1][0] if current_max_value.value() != target_min_value.value(): target_min_value.setValue(current_max_value.value()) elif mode == MIN_VALUE_MODE: current_min_value = self.threshold_classes.values()[ double_spin_index][0] target_max_value = self.threshold_classes.values()[ double_spin_index - 1][1] if current_min_value.value() != target_max_value.value(): target_max_value.setValue(current_min_value.value()) # Set behaviour for k, v in self.threshold_classes.items(): index = self.threshold_classes.keys().index(k) if index < len(self.threshold_classes) - 1: # Max value changed v[1].valueChanged.connect(partial( min_max_changed, double_spin_index=index, mode=MAX_VALUE_MODE)) if index > 0: # Min value v[0].valueChanged.connect(partial( min_max_changed, double_spin_index=index, mode=MIN_VALUE_MODE)) grid_layout_thresholds.setSpacing(0) self.right_layout.addLayout(grid_layout_thresholds) def add_buttons(self, classification): """Helper to setup 3 buttons. :param classification: The current classification. :type classification: dict """ # Note(IS): Until we have good behaviour, we will disable load # default and cancel button. # Add 3 buttons: Load default, Cancel, Save # load_default_button = QPushButton(tr('Load Default')) # cancel_button = QPushButton(tr('Cancel')) self.save_button = QPushButton(tr('Save')) # Action for buttons # cancel_button.clicked.connect(self.cancel_button_clicked) self.save_button.clicked.connect( partial(self.save_button_clicked, classification=classification)) button_layout = QHBoxLayout() # button_layout.addWidget(load_default_button) button_layout.addStretch(1) # button_layout.addWidget(cancel_button) button_layout.addWidget(self.save_button) button_layout.setStretch(0, 3) button_layout.setStretch(1, 1) # button_layout.setStretch(2, 1) # button_layout.setStretch(3, 1) self.right_layout.addLayout(button_layout) def setup_value_mapping_panels(self, classification): """Setup value mapping panel in the right panel. :param classification: Classification definition. :type classification: dict """ # Set text in the label layer_purpose = self.parent.step_kw_purpose.selected_purpose() layer_subcategory = self.parent.step_kw_subcategory. \ selected_subcategory() if is_raster_layer(self.parent.layer): description_text = classify_raster_question % ( layer_subcategory['name'], layer_purpose['name'], classification['name']) dataset = gdal.Open(self.parent.layer.source(), GA_ReadOnly) active_band = self.parent.step_kw_band_selector.selected_band() unique_values = numpy.unique(numpy.array( dataset.GetRasterBand(active_band).ReadAsArray())) field_type = 0 # Convert datatype to a json serializable type if numpy.issubdtype(unique_values.dtype, float): unique_values = [float(i) for i in unique_values] else: unique_values = [int(i) for i in unique_values] else: field = self.parent.step_kw_field.selected_fields() field_index = self.parent.layer.dataProvider().fields(). \ indexFromName(field) field_type = self.parent.layer.dataProvider(). \ fields()[field_index].type() description_text = classify_vector_question % ( layer_subcategory['name'], layer_purpose['name'], classification['name'], field.upper()) unique_values = self.parent.layer.uniqueValues(field_index) # Set description description_label = QLabel(description_text) description_label.setWordWrap(True) self.right_layout.addWidget(description_label) self.list_unique_values = QListWidget() self.list_unique_values.setDragDropMode(QAbstractItemView.DragDrop) self.list_unique_values.setDefaultDropAction(Qt.MoveAction) self.tree_mapping_widget = QTreeWidget() self.tree_mapping_widget.setDragDropMode(QAbstractItemView.DragDrop) self.tree_mapping_widget.setDefaultDropAction(Qt.MoveAction) self.tree_mapping_widget.header().hide() self.tree_mapping_widget.itemChanged.connect( self.update_dragged_item_flags) value_mapping_layout = QHBoxLayout() value_mapping_layout.addWidget(self.list_unique_values) value_mapping_layout.addWidget(self.tree_mapping_widget) self.right_layout.addLayout(value_mapping_layout) default_classes = classification['classes'] # Assign unique values to classes (according to default) unassigned_values = list() assigned_values = dict() for default_class in default_classes: assigned_values[default_class['key']] = list() for unique_value in unique_values: if unique_value is None or isinstance( unique_value, QPyNullVariant): # Don't classify features with NULL value continue # Capitalization of the value and removing '_' (raw OSM data). value_as_string = unicode(unique_value).upper().replace('_', ' ') assigned = False for default_class in default_classes: if 'string_defaults' in default_class: condition_1 = ( field_type > 9 and value_as_string in [ c.upper() for c in default_class['string_defaults']]) else: condition_1 = False condition_2 = ( field_type < 10 and 'numeric_default_min' in default_class and 'numeric_default_max' in default_class and ( default_class['numeric_default_min'] <= unique_value < default_class['numeric_default_max'])) if condition_1 or condition_2: assigned_values[default_class['key']] += [unique_value] assigned = True if not assigned: # add to unassigned values list otherwise unassigned_values += [unique_value] self.populate_classified_values( unassigned_values, assigned_values, default_classes, self.list_unique_values, self.tree_mapping_widget ) # Current value map for exposure and classification available_classifications = self.value_maps.get( self.active_exposure['key']) if not available_classifications: return # Get active one current_classification = available_classifications.get( classification['key']) if not current_classification: return current_value_map = current_classification.get('classes') if not current_value_map: return unassigned_values = list() assigned_values = dict() for default_class in default_classes: assigned_values[default_class['key']] = list() for unique_value in unique_values: if unique_value is None or isinstance( unique_value, QPyNullVariant): # Don't classify features with NULL value continue # check in value map assigned = False for key, value_list in current_value_map.items(): if unique_value in value_list and key in assigned_values: assigned_values[key] += [unique_value] assigned = True if not assigned: unassigned_values += [unique_value] self.populate_classified_values( unassigned_values, assigned_values, default_classes, self.list_unique_values, self.tree_mapping_widget ) # noinspection PyMethodMayBeStatic def update_dragged_item_flags(self, item): """Fix the drop flag after the item is dropped. Check if it looks like an item dragged from QListWidget to QTreeWidget and disable the drop flag. For some reasons the flag is set when dragging. :param item: Item which is dragged. :type item: QTreeWidgetItem .. note:: This is a slot executed when the item change. """ if int(item.flags() & Qt.ItemIsDropEnabled) \ and int(item.flags() & Qt.ItemIsDragEnabled): item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled) @staticmethod def populate_classified_values( unassigned_values, assigned_values, default_classes, list_unique_values, tree_mapping_widget): """Populate lstUniqueValues and treeClasses.from the parameters. :param unassigned_values: List of values that haven't been assigned to a class. It will be put in list_unique_values. :type unassigned_values: list :param assigned_values: Dictionary with class as the key and list of value as the value of the dictionary. It will be put in tree_mapping_widget. :type assigned_values: dict :param default_classes: Default classes from unit. :type default_classes: list :param list_unique_values: List Widget for unique values :type list_unique_values: QListWidget :param tree_mapping_widget: Tree Widget for classifying. :type tree_mapping_widget: QTreeWidget """ # Populate the unique values list list_unique_values.clear() list_unique_values.setSelectionMode( QAbstractItemView.ExtendedSelection) for value in unassigned_values: value_as_string = value is not None and unicode(value) or 'NULL' list_item = QListWidgetItem(list_unique_values) list_item.setFlags( Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) list_item.setData(Qt.UserRole, value) list_item.setText(value_as_string) list_unique_values.addItem(list_item) # Populate assigned values tree tree_mapping_widget.clear() bold_font = QFont() bold_font.setItalic(True) bold_font.setBold(True) bold_font.setWeight(75) tree_mapping_widget.invisibleRootItem().setFlags( Qt.ItemIsEnabled) for default_class in default_classes: # Create branch for class tree_branch = QTreeWidgetItem(tree_mapping_widget) tree_branch.setFlags( Qt.ItemIsDropEnabled | Qt.ItemIsEnabled) tree_branch.setExpanded(True) tree_branch.setFont(0, bold_font) if 'name' in default_class: default_class_name = default_class['name'] else: default_class_name = default_class['key'] tree_branch.setText(0, default_class_name) tree_branch.setData(0, Qt.UserRole, default_class['key']) if 'description' in default_class: tree_branch.setToolTip(0, default_class['description']) # Assign known values for value in assigned_values[default_class['key']]: string_value = value is not None and unicode(value) or 'NULL' tree_leaf = QTreeWidgetItem(tree_branch) tree_leaf.setFlags( Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) tree_leaf.setData(0, Qt.UserRole, value) tree_leaf.setText(0, string_value) def cancel_button_clicked(self): """Action for cancel button clicked.""" # Change mode self.mode = CHOOSE_MODE # Enable all edit buttons and combo boxes for i in range(len(self.exposures)): if i == self.special_case_index: self.exposure_edit_buttons[i].setEnabled(False) self.exposure_combo_boxes[i].setEnabled(False) continue if self.get_classification(self.exposure_combo_boxes[i]): self.exposure_edit_buttons[i].setEnabled(True) else: self.exposure_edit_buttons[i].setEnabled(False) # self.exposure_edit_buttons[i].setText(tr('Edit')) self.exposure_combo_boxes[i].setEnabled(True) # Clear right panel clear_layout(self.right_layout) # Show current state self.show_current_state() # Unset active exposure self.active_exposure = None self.parent.pbnNext.setEnabled(self.is_ready_to_next_step()) def save_button_clicked(self, classification): """Action for save button clicked. :param classification: The classification that being edited. :type classification: dict """ # Save current edit if self.layer_mode == layer_mode_continuous: thresholds = self.get_threshold() classification_class = { 'classes': thresholds, 'active': True } if self.thresholds.get(self.active_exposure['key']): # Set other class to not active for current_classification in self.thresholds.get( self.active_exposure['key']).values(): current_classification['active'] = False else: self.thresholds[self.active_exposure['key']] = {} self.thresholds[self.active_exposure['key']][ classification['key']] = classification_class else: value_maps = self.get_value_map() classification_class = { 'classes': value_maps, 'active': True } if self.value_maps.get(self.active_exposure['key']): # Set other class to not active for current_classification in self.value_maps.get( self.active_exposure['key']).values(): current_classification['active'] = False else: self.value_maps[self.active_exposure['key']] = {} self.value_maps[self.active_exposure['key']][ classification['key']] = classification_class # Back to choose mode self.cancel_button_clicked() def get_threshold(self): """Return threshold based on current state.""" value_map = dict() for key, value in self.threshold_classes.items(): value_map[key] = [ value[0].value(), value[1].value(), ] return value_map def get_value_map(self): """Obtain the value-to-class mapping set by user. :returns: The complete mapping as a dict of lists. :rtype: dict """ value_map = {} tree_clone = self.tree_mapping_widget.invisibleRootItem().clone() for tree_branch in tree_clone.takeChildren(): value_list = [] for tree_leaf in tree_branch.takeChildren(): value_list += [tree_leaf.data(0, Qt.UserRole)] if value_list: value_map[tree_branch.data(0, Qt.UserRole)] = value_list return value_map def set_current_state(self): """"Helper to set the state of the step from current keywords.""" if not self.thresholds: self.thresholds = self.parent.get_existing_keyword('thresholds') if not self.value_maps: self.value_maps = self.parent.get_existing_keyword('value_maps') def classifications_combo_box_changed( self, index, exposure, exposure_combo_box, edit_button): """Action when classification combo box changed. :param index: The index of the combo box. :type index: int :param exposure: The exposure associated with the combo box. :type exposure: dict :param exposure_combo_box: Combo box for the classification. :type exposure_combo_box: QComboBox :param edit_button: The edit button associate with combo box. :type edit_button: QPushButton """ # Disable button if it's no classification edit_button.setEnabled(bool(index)) classification = self.get_classification(exposure_combo_box) self.activate_classification(exposure, classification) clear_layout(self.right_layout) self.show_current_state() self.parent.pbnNext.setEnabled(self.is_ready_to_next_step()) # Open edit panel directly edit_button.click() def activate_classification(self, exposure, classification=None): """Set active to True for classification for the exposure. If classification = None, all classification set active = False. :param exposure: Exposure definition. :type exposure: dict :param classification: Classification definition. :type classification: dict """ if self.layer_mode == layer_mode_continuous: selected_unit = self.parent.step_kw_unit.selected_unit()['key'] target = self.thresholds.get(exposure['key']) if target is None: self.thresholds[exposure['key']] = {} target = self.thresholds.get(exposure['key']) else: selected_unit = None target = self.value_maps.get(exposure['key']) if target is None: self.value_maps[exposure['key']] = {} target = self.value_maps.get(exposure['key']) if classification is not None: if classification['key'] not in target: if self.layer_mode == layer_mode_continuous: default_classes = default_classification_thresholds( classification, selected_unit) target[classification['key']] = { 'classes': default_classes, 'active': True } else: default_classes = default_classification_value_maps( classification) target[classification['key']] = { 'classes': default_classes, 'active': True } return for classification_key, value in target.items(): if classification is None: value['active'] = False continue if classification_key == classification['key']: value['active'] = True else: value['active'] = False @property def step_name(self): """Get the human friendly name for the wizard step. :returns: The name of the wizard step. :rtype: str """ return tr('Multi Classification Step') def help_content(self): """Return the content of help for this step wizard. We only needs to re-implement this method in each wizard step. :returns: A message object contains help. :rtype: m.Message """ message = m.Message() message.add(m.Paragraph(tr( 'In this wizard step: {step_name}, you will be able to set the ' 'classification that you will use per exposure type. You can also ' 'set the threshold or value map for each classification.' ).format(step_name=self.step_name))) return message
class ChangedDocumentsListDialog(widgets.dialog.Dialog): def __init__(self): super(ChangedDocumentsListDialog, self).__init__(buttons=('close', )) self.setWindowModality(Qt.NonModal) self.setAttribute(Qt.WA_QuitOnClose, False) layout = QGridLayout(margin=0) self.mainWidget().setLayout(layout) self.tree = QTreeWidget(headerHidden=True, rootIsDecorated=False, columnCount=2, itemsExpandable=False) self.tree.setSelectionMode(QTreeWidget.ExtendedSelection) self.buttonReload = QPushButton() self.buttonReloadAll = QPushButton() self.buttonSave = QPushButton() self.buttonSaveAll = QPushButton() self.buttonShowDiff = QPushButton() self.checkWatchingEnabled = QCheckBox(checked=enabled()) layout.addWidget(self.tree, 0, 0, 6, 1) layout.addWidget(self.buttonReload, 0, 1) layout.addWidget(self.buttonReloadAll, 1, 1) layout.addWidget(self.buttonSave, 2, 1) layout.addWidget(self.buttonSaveAll, 3, 1) layout.addWidget(self.buttonShowDiff, 4, 1) layout.addWidget(self.checkWatchingEnabled, 6, 0, 1, 2) layout.setRowStretch(5, 10) app.documentClosed.connect(self.removeDocument) app.documentSaved.connect(self.removeDocument) app.documentUrlChanged.connect(self.removeDocument) app.documentLoaded.connect(self.removeDocument) self.tree.itemSelectionChanged.connect(self.updateButtons) self.buttonReload.clicked.connect(self.slotButtonReload) self.buttonReloadAll.clicked.connect(self.slotButtonReloadAll) self.buttonSave.clicked.connect(self.slotButtonSave) self.buttonSaveAll.clicked.connect(self.slotButtonSaveAll) self.buttonShowDiff.clicked.connect(self.slotButtonShowDiff) self.checkWatchingEnabled.toggled.connect(setEnabled) app.translateUI(self) qutil.saveDialogSize(self, 'externalchanges/dialog/size', QSize(400, 200)) userguide.addButton(self.buttonBox(), "externalchanges") self.button('close').setFocus() def translateUI(self): self.setWindowTitle(app.caption(_("Modified Files"))) self.setMessage( _("The following files were modified or deleted by other " "applications:")) self.buttonReload.setText(_("Reload")) self.buttonReload.setToolTip( _("Reloads the selected documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonReloadAll.setText(_("Reload All")) self.buttonReloadAll.setToolTip( _("Reloads all externally modified documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonSave.setText(_("Save")) self.buttonSave.setToolTip( _("Saves the selected documents to disk, overwriting the " "modifications by another program.")) self.buttonSaveAll.setText(_("Save All")) self.buttonSaveAll.setToolTip( _("Saves all documents to disk, overwriting the modifications by " "another program.")) self.buttonShowDiff.setText(_("Show Difference...")) self.buttonShowDiff.setToolTip( _("Shows the differences between the current document " "and the file on disk.")) self.checkWatchingEnabled.setText( _("Enable watching documents for external changes")) self.checkWatchingEnabled.setToolTip( _("If checked, Frescobaldi will warn you when opened files are " "modified or deleted by other applications.")) def setDocuments(self, documents): """Display the specified documents in the list.""" # clear the treewidget for d in self.tree.invisibleRootItem().takeChildren(): for i in d.takeChildren(): i.doc = None # group the documents by directory dirs = {} for d in documents: path = d.url().toLocalFile() if path: dirname, filename = os.path.split(path) dirs.setdefault(dirname, []).append((filename, d)) for dirname in sorted(dirs, key=util.naturalsort): diritem = QTreeWidgetItem() diritem.setText(0, util.homify(dirname)) self.tree.addTopLevelItem(diritem) diritem.setExpanded(True) diritem.setFlags(Qt.ItemIsEnabled) diritem.setIcon(0, icons.get('folder-open')) for filename, document in sorted( dirs[dirname], key=lambda item: util.naturalsort(item[0])): fileitem = QTreeWidgetItem() diritem.addChild(fileitem) if documentwatcher.DocumentWatcher.instance( document).isdeleted(): itemtext = _("[deleted]") icon = "dialog-error" else: itemtext = _("[modified]") icon = "document-edit" fileitem.setIcon(0, icons.get(icon)) fileitem.setText(0, filename) fileitem.setText(1, itemtext) fileitem.doc = document # select the item if there is only one if len(dirs) == 1 and len(list(dirs.values())[0]) == 1: fileitem.setSelected(True) self.tree.resizeColumnToContents(0) self.tree.resizeColumnToContents(1) self.updateButtons() def removeDocument(self, document): """Remove the specified document from our list.""" for d in range(self.tree.topLevelItemCount()): diritem = self.tree.topLevelItem(d) for f in range(diritem.childCount()): if diritem.child(f).doc is document: i = diritem.takeChild(f) i.doc = None if diritem.childCount() == 0: self.tree.takeTopLevelItem(d) break else: continue break self.updateButtons() # hide if no documents are left if self.tree.topLevelItemCount() == 0: self.hide() def selectedDocuments(self): """Return the selected documents.""" return [i.doc for i in self.tree.selectedItems()] def allDocuments(self): """Return all shown documents.""" return [ self.tree.topLevelItem(d).child(f).doc for d in range(self.tree.topLevelItemCount()) for f in range(self.tree.topLevelItem(d).childCount()) ] def updateButtons(self): """Updates the buttons regarding the selection.""" docs_sel = self.selectedDocuments() docs_all = self.allDocuments() all_deleted_sel = all( documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_sel) all_deleted_all = all( documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_all) self.buttonSave.setEnabled(len(docs_sel) > 0) self.buttonSaveAll.setEnabled(len(docs_all) > 0) self.buttonReload.setEnabled(not all_deleted_sel) self.buttonReloadAll.setEnabled(not all_deleted_all) self.buttonShowDiff.setEnabled( len(docs_sel) == 1 and not all_deleted_sel) def slotButtonReload(self): """Called when the user clicks Reload.""" self.reloadDocuments(self.selectedDocuments()) def slotButtonReloadAll(self): """Called when the user clicks Reload All.""" self.reloadDocuments(self.allDocuments()) def slotButtonSave(self): """Called when the user clicks Save.""" self.saveDocuments(self.selectedDocuments()) def slotButtonSaveAll(self): """Called when the user clicks Save All.""" self.saveDocuments(self.allDocuments()) def reloadDocuments(self, documents): """Used by slotButtonReload and slotButtonReloadAll.""" failures = [] for d in documents: try: d.load(keepUndo=True) except IOError as e: failures.append((d, e)) if failures: msg = _("Could not reload:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format(url=d.url().toLocalFile(), strerror=e.strerror, errno=e.errno) for d, e in failures) QMessageBox.critical(self, app.caption(_("Error")), msg) def saveDocuments(self, documents): """Used by slotButtonSave and slotButtonSaveAll.""" failures = [] for d in documents: try: d.save() except IOError as e: failures.append((d, e)) if failures: msg = _("Could not save:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format( url = d.url().toLocalFile(), strerror = e.strerror, errno = e.errno) for d, e in failures) + "\n\n" + \ _("Please save the document using the \"Save As...\" dialog.", "Please save the documents using the \"Save As...\" dialog.", len(failures)) QMessageBox.critical(self, app.caption(_("Error")), msg) def slotButtonShowDiff(self): """Called when the user clicks Show Difference.""" docs = self.selectedDocuments() or self.allDocuments() if not docs: return d = docs[0] if documentwatcher.DocumentWatcher.instance(d).isdeleted(): return filename = d.url().toLocalFile() try: with open(filename, 'rb') as f: disktext = util.decode(f.read()) except (IOError, OSError): return currenttext = d.toPlainText() html = htmldiff.htmldiff(currenttext, disktext, _("Current Document"), _("Document on Disk"), numlines=5) dlg = widgets.dialog.Dialog(self, buttons=('close', )) view = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap) view.setHtml(html) dlg.setMainWidget(view) dlg.setWindowTitle(app.caption("Differences")) dlg.setMessage( _("Document: {url}\n" "Difference between the current document and the file on disk:"). format(url=filename)) dlg.setWindowModality(Qt.NonModal) dlg.setAttribute(Qt.WA_QuitOnClose, False) dlg.setAttribute(Qt.WA_DeleteOnClose) qutil.saveDialogSize(dlg, "externalchanges/diff/dialog/size", QSize(600, 300)) dlg.show()
class DictParameterWidget(GenericParameterWidget): """Widget class for DictParameter.""" def __init__(self, parameter, parent=None): """Constructor .. versionadded:: 3.1 :param parameter: A DictParameter object. :type parameter: DictParameter """ # pylint: disable=E1002 super(DictParameterWidget, self).__init__(parameter, parent) # pylint: enable=E1002 self.input = QTreeWidget() # generate tree model widget_items = self.generate_tree_model(self._parameter.value) self.input.addTopLevelItems(widget_items) # set header self.input.headerItem().setText(0, 'Keys') self.input.headerItem().setText(1, 'Values') self.inner_input_layout.addWidget(self.input) # override self._input_layout arrangement to make the label at the top # reset the layout self.input_layout.setParent(None) self.help_layout.setParent(None) self.label.setParent(None) self.inner_input_layout.setParent(None) self.input_layout = QVBoxLayout() self.input_layout.setSpacing(0) # put element into layout self.input_layout.addWidget(self.label) self.input_layout.addLayout(self.inner_input_layout) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) def generate_tree_model(self, data_dict): """Generate a tree model for specified dictionary :param data_dict: A dictionary :type data_dict: dict :return: list of QTreeWidgetItem :rtype list: """ widget_items = [] font = QFont() font.setBold(True) for key in data_dict.keys(): entry = data_dict[key] key_item = QTreeWidgetItem() key_item.setText(0, str(key)) key_item.setFont(0, font) if isinstance(entry, dict): items = self.generate_tree_model(entry) key_item.addChildren(items) else: # value_item = QTreeWidgetItem() key_item.setText(1, str(entry)) key_item.setFlags(key_item.flags() | Qt.ItemIsEditable) # key_item.addChild(key_item) widget_items.append(key_item) return widget_items def extract_dict(self, widget_items): """Extract dictionary key and values from QTreeWidgetItems :param widget_items: List of QTreeWidgetItems :type widget_items: list :return: hierarchical dictionary extracted from widget_items :rtype dict: """ data_dict = {} element_type = self._parameter.element_type if element_type == object: def object_cast(obj): return obj element_type = object_cast for key_item in widget_items: key = str(key_item.text(0)) value = None if key_item.childCount() == 0: # value_item = key_item.child(0) value = element_type(key_item.text(1)) elif key_item.childCount() > 1: value_items = [key_item.child(i) for i in range(key_item.childCount())] value = self.extract_dict(value_items) data_dict[key] = value return data_dict def get_parameter(self): """Obtain the parameter object from the current widget state. :returns: A DictParameter from the current state of widget """ root_widget_item = self.input.invisibleRootItem() widget_items = [root_widget_item.child(i) for i in range(root_widget_item.childCount())] data_dict = self.extract_dict(widget_items) self._parameter.value = data_dict return self._parameter
class NetworkArgs(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ Network arguments dialog """ def __init__(self, dataArgs, parent=None): """ Dialog to fill arguments for the network probe @param dataArgs: @type dataArgs: @param parent: @type parent: """ super(NetworkArgs, self).__init__(parent) self.dataArgs = dataArgs self.createDialog() self.createConnections() self.loadDefaultData() def createDialog (self): """ Create qt dialog """ mainLayout = QHBoxLayout() paramLayout = QHBoxLayout() paramLayout.addWidget( QLabel("Interface:") ) self.intComboBox = QComboBox() self.intComboBox.setEditable(1) self.intComboBox.addItems( [ 'any', 'eth0', 'eth1', 'eth2', 'eth3', 'eth4', 'lo0' ] ) paramLayout.addWidget( self.intComboBox ) paramLayout.addWidget( QLabel("Filter:") ) self.filterEdit = QLineEdit() paramLayout.addWidget( self.filterEdit ) dataLayout = QVBoxLayout() self.labelHelp = QLabel("Network interface to dump:\nIf the interface name does not exist in the list\nplease to edit the combox list to change it.") self.listBox = QTreeWidget(self) self.listBox.setIndentation(0) self.labels = [ self.tr("Interface"), self.tr("Filter") ] self.listBox.setHeaderLabels(self.labels) dataLayout.addWidget( self.labelHelp ) dataLayout.addLayout( paramLayout ) dataLayout.addWidget( self.listBox ) buttonLayout = QVBoxLayout() self.addButton = QPushButton("Add", self) self.delButton = QPushButton("Remove", self) self.delButton.setEnabled(False) self.editButton = QPushButton("Edit", self) self.editButton.setEnabled(False) self.clearButton = QPushButton("Clear", self) self.okButton = QPushButton("Ok", self) self.cancelButton = QPushButton("Cancel", self) buttonLayout.addWidget( self.addButton ) buttonLayout.addWidget( self.delButton ) buttonLayout.addWidget( self.editButton ) buttonLayout.addWidget( self.clearButton ) buttonLayout.addWidget( self.okButton ) buttonLayout.addWidget( self.cancelButton ) mainLayout.addLayout( dataLayout ) mainLayout.addLayout( buttonLayout ) self.setLayout(mainLayout) self.setWindowTitle("Network Probe > Arguments") def createConnections (self): """ Create qt connections """ self.okButton.clicked.connect(self.accept) self.cancelButton.clicked.connect(self.reject) self.addButton.clicked.connect(self.addItem) self.delButton.clicked.connect(self.delItem) self.editButton.clicked.connect(self.editItem) self.clearButton.clicked.connect(self.clearList) self.listBox.itemClicked.connect(self.onItemSelected) def clearList(self): """ Clear the list """ self.listBox.clear() def onItemSelected(self, itm, row): """ Called when an item is selected """ self.delButton.setEnabled(True) self.editButton.setEnabled(True) def editItem(self): """ Edit item """ self.delButton.setEnabled(False) self.editButton.setEnabled(False) # retrieve value to put it in the line edit and then remove item model = self.listBox.model() for selectedItem in self.listBox.selectedItems(): qIndex = self.listBox.indexFromItem(selectedItem) eth = selectedItem.dataNet['interface'] flt = selectedItem.dataNet['filter'] self.filterEdit.setText( flt ) self.intComboBox.setEditText( eth ) model.removeRow(qIndex.row()) def delItem(self): """ Delete item """ self.delButton.setEnabled(False) self.editButton.setEnabled(False) # remove item model = self.listBox.model() for selectedItem in self.listBox.selectedItems(): qIndex = self.listBox.indexFromItem(selectedItem) model.removeRow(qIndex.row()) def addItem(self): """ Add item """ eth = self.intComboBox.currentText() if eth != '': flt = self.filterEdit.text() tpl = {'interface': str(eth), 'filter': str(flt) } newParam = NetItem( data=tpl, parent=self.listBox) self.listBox.resizeColumnToContents(0) def loadDefaultData(self): """ Load the default data """ try: if len(self.dataArgs) ==0: return datObj = eval(str(self.dataArgs)) if 'interfaces' in datObj: for eth in datObj['interfaces']: newParam = NetItem( data=eth, parent=self.listBox) except Exception as e: self.error( "unable to load the default data: %s" % e ) def getArgs(self): """ Returns arguments Example list of files: {'interfaces': [ {'interface':'any', 'filter':''} ] } """ listEth = [] # iterate all items in a QListWidget root = self.listBox.invisibleRootItem() child_count = root.childCount() for i in xrange(child_count): itm = root.child(i) listEth.append( eval(str(itm.dataNet)) ) ret = {'interfaces': listEth } if len(listEth) == 0: ret = '' return str(ret)
class DictParameterWidget(GenericParameterWidget): """Widget class for DictParameter.""" def __init__(self, parameter, parent=None): """Constructor .. versionadded:: 3.1 :param parameter: A DictParameter object. :type parameter: DictParameter """ # pylint: disable=E1002 super(DictParameterWidget, self).__init__(parameter, parent) # pylint: enable=E1002 self._input = QTreeWidget() # generate tree model widget_items = self.generate_tree_model(self._parameter.value) self._input.addTopLevelItems(widget_items) # set header self._input.headerItem().setText(0, 'Keys') self._input.headerItem().setText(1, 'Values') self._inner_input_layout.addWidget(self._input) # override self._input_layout arrangement to make the label at the top # reset the layout self._input_layout.setParent(None) self._help_layout.setParent(None) self._label.setParent(None) self._inner_input_layout.setParent(None) self._input_layout = QVBoxLayout() self._input_layout.setSpacing(0) # put element into layout self._input_layout.addWidget(self._label) self._input_layout.addLayout(self._inner_input_layout) self._main_layout.addLayout(self._input_layout) self._main_layout.addLayout(self._help_layout) def generate_tree_model(self, data_dict): """Generate a tree model for specified dictionary :param data_dict: A dictionary :type data_dict: dict :return: list of QTreeWidgetItem :rtype list: """ widget_items = [] font = QFont() font.setBold(True) for key in data_dict.keys(): entry = data_dict[key] key_item = QTreeWidgetItem() key_item.setText(0, str(key)) key_item.setFont(0, font) if isinstance(entry, dict): items = self.generate_tree_model(entry) key_item.addChildren(items) else: # value_item = QTreeWidgetItem() key_item.setText(1, str(entry)) key_item.setFlags(key_item.flags() | Qt.ItemIsEditable) # key_item.addChild(key_item) widget_items.append(key_item) return widget_items def extract_dict(self, widget_items): """Extract dictionary key and values from QTreeWidgetItems :param widget_items: List of QTreeWidgetItems :type widget_items: list :return: hierarchical dictionary extracted from widget_items :rtype dict: """ data_dict = {} element_type = self._parameter.element_type if element_type == object: def object_cast(obj): return obj element_type = object_cast for key_item in widget_items: key = str(key_item.text(0)) value = None if key_item.childCount() == 0: # value_item = key_item.child(0) value = element_type(key_item.text(1)) elif key_item.childCount() > 1: value_items = [key_item.child(i) for i in range(key_item.childCount())] value = self.extract_dict(value_items) data_dict[key] = value return data_dict def get_parameter(self): """Obtain the parameter object from the current widget state. :returns: A DictParameter from the current state of widget """ root_widget_item = self._input.invisibleRootItem() widget_items = [root_widget_item.child(i) for i in range(root_widget_item.childCount())] data_dict = self.extract_dict(widget_items) self._parameter.value = data_dict return self._parameter
class OWGEODatasets(OWWidget): name = "GEO Data Sets" description = DESCRIPTION icon = "../widgets/icons/GEODataSets.svg" priority = PRIORITY inputs = [] outputs = [("Expression Data", Orange.data.Table)] settingsList = ["outputRows", "mergeSpots", "gdsSelectionStates", "splitterSettings", "currentGds", "autoCommit", "datasetNames"] outputRows = Setting(False) mergeSpots = Setting(True) gdsSelectionStates = Setting({}) currentGds = Setting(None) datasetNames = Setting({}) splitterSettings = Setting( (b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xea\x00\x00\x00\xd7\x01\x00\x00\x00\x07\x01\x00\x00\x00\x02', b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xb5\x00\x00\x02\x10\x01\x00\x00\x00\x07\x01\x00\x00\x00\x01') ) autoCommit = Setting(True) def __init__(self, parent=None, signalManager=None, name=" GEO Data Sets"): OWWidget.__init__(self, parent, signalManager, name) self.selectionChanged = False self.filterString = "" self.datasetName = "" ## GUI box = gui.widgetBox(self.controlArea, "Info", addSpace=True) self.infoBox = gui.widgetLabel(box, "Initializing\n\n") box = gui.widgetBox(self.controlArea, "Output", addSpace=True) gui.radioButtonsInBox(box, self, "outputRows", ["Genes or spots", "Samples"], "Rows", callback=self.commitIf) gui.checkBox(box, self, "mergeSpots", "Merge spots of same gene", callback=self.commitIf) gui.separator(box) self.nameEdit = gui.lineEdit( box, self, "datasetName", "Data set name", tooltip="Override the default output data set name", callback=self.onNameEdited ) self.nameEdit.setPlaceholderText("") if sys.version_info < (3, ): box = gui.widgetBox(self.controlArea, "Commit", addSpace=True) self.commitButton = gui.button( box, self, "Commit", callback=self.commit) cb = gui.checkBox(box, self, "autoCommit", "Commit on any change") gui.setStopper(self, self.commitButton, cb, "selectionChanged", self.commit) else: gui.auto_commit(self.controlArea, self, "autoCommit", "Commit", box="Commit") gui.rubber(self.controlArea) # self.filterLineEdit = OWGUIEx.lineEditHint( # self.mainArea, self, "filterString", "Filter", # caseSensitive=False, matchAnywhere=True, # callback=self.filter, delimiters=" ") gui.widgetLabel(self.mainArea, "Filter") self.filterLineEdit = QLineEdit( textChanged=self.filter ) self.completer = QCompleter( caseSensitivity=Qt.CaseInsensitive ) self.completer.setModel(QStringListModel(self)) self.filterLineEdit.setCompleter(self.completer) self.mainArea.layout().addWidget(self.filterLineEdit) splitter = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(splitter) self.treeWidget = QTreeView(splitter) self.treeWidget.setSelectionMode(QTreeView.SingleSelection) self.treeWidget.setRootIsDecorated(False) self.treeWidget.setSortingEnabled(True) self.treeWidget.setAlternatingRowColors(True) self.treeWidget.setUniformRowHeights(True) self.treeWidget.setEditTriggers(QTreeView.NoEditTriggers) linkdelegate = LinkStyledItemDelegate(self.treeWidget) self.treeWidget.setItemDelegateForColumn(1, linkdelegate) self.treeWidget.setItemDelegateForColumn(8, linkdelegate) self.treeWidget.setItemDelegateForColumn( 0, gui.IndicatorItemDelegate(self.treeWidget, role=Qt.DisplayRole)) proxyModel = MySortFilterProxyModel(self.treeWidget) self.treeWidget.setModel(proxyModel) self.treeWidget.selectionModel().selectionChanged.connect( self.updateSelection ) self.treeWidget.viewport().setMouseTracking(True) splitterH = QSplitter(Qt.Horizontal, splitter) box = gui.widgetBox(splitterH, "Description") self.infoGDS = gui.widgetLabel(box, "") self.infoGDS.setWordWrap(True) gui.rubber(box) box = gui.widgetBox(splitterH, "Sample Annotations") self.annotationsTree = QTreeWidget(box) self.annotationsTree.setHeaderLabels( ["Type (Sample annotations)", "Sample count"] ) self.annotationsTree.setRootIsDecorated(True) box.layout().addWidget(self.annotationsTree) self.annotationsTree.itemChanged.connect( self.annotationSelectionChanged ) self._annotationsUpdating = False self.splitters = splitter, splitterH for sp, setting in zip(self.splitters, self.splitterSettings): sp.splitterMoved.connect(self.splitterMoved) sp.restoreState(setting) self.searchKeys = ["dataset_id", "title", "platform_organism", "description"] self.gds = [] self.gds_info = None self.resize(1000, 600) self.setBlocking(True) self.setEnabled(False) self.progressBarInit() self._executor = ThreadExecutor() func = partial(get_gds_model, methodinvoke(self, "_setProgress", (float,))) self._inittask = Task(function=func) self._inittask.finished.connect(self._initializemodel) self._executor.submit(self._inittask) self._datatask = None @Slot(float) def _setProgress(self, value): self.progressBarValue = value def _initializemodel(self): assert self.thread() is QThread.currentThread() model, self.gds_info, self.gds = self._inittask.result() model.setParent(self) proxy = self.treeWidget.model() proxy.setFilterKeyColumn(0) proxy.setFilterRole(TextFilterRole) proxy.setFilterCaseSensitivity(False) proxy.setFilterFixedString(self.filterString) proxy.setSourceModel(model) proxy.sort(0, Qt.DescendingOrder) self.progressBarFinished() self.setBlocking(False) self.setEnabled(True) filter_items = " ".join( gds[key] for gds in self.gds for key in self.searchKeys ) tr_chars = ",.:;!?(){}[]_-+\\|/%#@$^&*<>~`" tr_table = str.maketrans(tr_chars, " " * len(tr_chars)) filter_items = filter_items.translate(tr_table) filter_items = sorted(set(filter_items.split(" "))) filter_items = [item for item in filter_items if len(item) > 3] self.completer.model().setStringList(filter_items) # self.filterLineEdit.setItems(filter_items) if self.currentGds: current_id = self.currentGds["dataset_id"] gdss = [(i, qunpack(proxy.data(proxy.index(i, 1), Qt.DisplayRole))) for i in range(proxy.rowCount())] current = [i for i, data in gdss if data and data == current_id] if current: current_index = proxy.index(current[0], 0) self.treeWidget.selectionModel().select( current_index, QItemSelectionModel.Select | QItemSelectionModel.Rows ) self.treeWidget.scrollTo( current_index, QTreeView.PositionAtCenter) for i in range(8): self.treeWidget.resizeColumnToContents(i) self.treeWidget.setColumnWidth( 1, min(self.treeWidget.columnWidth(1), 300)) self.treeWidget.setColumnWidth( 2, min(self.treeWidget.columnWidth(2), 200)) self.updateInfo() def updateInfo(self): gds_info = self.gds_info text = ("%i datasets\n%i datasets cached\n" % (len(gds_info), len(glob.glob(serverfiles.localpath("GEO") + "/GDS*")))) filtered = self.treeWidget.model().rowCount() if len(self.gds) != filtered: text += ("%i after filtering") % filtered self.infoBox.setText(text) def updateSelection(self, *args): current = self.treeWidget.selectedIndexes() mapToSource = self.treeWidget.model().mapToSource current = [mapToSource(index).row() for index in current] if current: self.currentGds = self.gds[current[0]] self.setAnnotations(self.currentGds) self.infoGDS.setText(self.currentGds.get("description", "")) self.nameEdit.setPlaceholderText(self.currentGds["title"]) self.datasetName = \ self.datasetNames.get(self.currentGds["dataset_id"], "") else: self.currentGds = None self.nameEdit.setPlaceholderText("") self.datasetName = "" self.commitIf() def setAnnotations(self, gds): self._annotationsUpdating = True self.annotationsTree.clear() annotations = defaultdict(set) subsetscount = {} for desc in gds["subsets"]: annotations[desc["type"]].add(desc["description"]) subsetscount[desc["description"]] = str(len(desc["sample_id"])) for type, subsets in annotations.items(): key = (gds["dataset_id"], type) subsetItem = QTreeWidgetItem(self.annotationsTree, [type]) subsetItem.setFlags(subsetItem.flags() | Qt.ItemIsUserCheckable | Qt.ItemIsTristate) subsetItem.setCheckState( 0, self.gdsSelectionStates.get(key, Qt.Checked) ) subsetItem.key = key for subset in subsets: key = (gds["dataset_id"], type, subset) item = QTreeWidgetItem( subsetItem, [subset, subsetscount.get(subset, "")] ) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState( 0, self.gdsSelectionStates.get(key, Qt.Checked) ) item.key = key self._annotationsUpdating = False self.annotationsTree.expandAll() for i in range(self.annotationsTree.columnCount()): self.annotationsTree.resizeColumnToContents(i) def annotationSelectionChanged(self, item, column): if self._annotationsUpdating: return for i in range(self.annotationsTree.topLevelItemCount()): item = self.annotationsTree.topLevelItem(i) self.gdsSelectionStates[item.key] = item.checkState(0) for j in range(item.childCount()): child = item.child(j) self.gdsSelectionStates[child.key] = child.checkState(0) def filter(self): filter_string = unicode(self.filterLineEdit.text()) proxyModel = self.treeWidget.model() if proxyModel: strings = filter_string.lower().strip().split() proxyModel.setFilterFixedStrings(strings) self.updateInfo() def selectedSamples(self): """ Return the currently selected sample annotations. The return value is a list of selected (sample type, sample value) tuples. .. note:: if some Sample annotation type has no selected values. this method will return all values for it. """ samples = [] unused_types = [] used_types = [] for stype in childiter(self.annotationsTree.invisibleRootItem()): selected_values = [] all_values = [] for sval in childiter(stype): value = (str(stype.text(0)), str(sval.text(0))) if self.gdsSelectionStates.get(sval.key, True): selected_values.append(value) all_values.append(value) if selected_values: samples.extend(selected_values) used_types.append(str(stype.text(0))) else: # If no sample of sample type is selected we don't filter # on it. samples.extend(all_values) unused_types.append(str(stype.text(0))) return samples, used_types def commitIf(self): if self.autoCommit: self.commit() else: self.selectionChanged = True def commit(self): if self.currentGds: self.error(0) sample_type = None self.progressBarInit() self.progressBarSet(10) _, groups = self.selectedSamples() if len(groups) == 1 and self.outputRows: sample_type = groups[0] self.setEnabled(False) self.setBlocking(True) def get_data(gds_id, report_genes, transpose, sample_type, title): gds = geo.GDS(gds_id) data = gds.getdata( report_genes=report_genes, transpose=transpose, sample_type=sample_type ) data.name = title return data get_data = partial( get_data, self.currentGds["dataset_id"], report_genes=self.mergeSpots, transpose=self.outputRows, sample_type=sample_type, title=self.datasetName or self.currentGds["title"] ) self._datatask = Task(function=get_data) self._datatask.finished.connect(self._on_dataready) self._executor.submit(self._datatask) def _on_dataready(self): self.setEnabled(True) self.setBlocking(False) self.progressBarSet(50) try: data = self._datatask.result() except urlrequest.URLError as error: self.error(0, "Error while connecting to the NCBI ftp server! %r" % error) self._datatask = None self.progressBarFinished() return self._datatask = None data_name = data.name samples, _ = self.selectedSamples() self.warning(0) message = None if self.outputRows: def samplesinst(ex): out = [] for meta in data.domain.metas: out.append((meta.name, ex[meta].value)) if data.domain.class_var.name != 'class': out.append((data.domain.class_var.name, ex[data.domain.class_var].value)) return out samples = set(samples) mask = [samples.issuperset(samplesinst(ex)) for ex in data] data = data[numpy.array(mask, dtype=bool)] if len(data) == 0: message = "No samples with selected sample annotations." else: samples = set(samples) domain = Orange.data.Domain( [attr for attr in data.domain.attributes if samples.issuperset(attr.attributes.items())], data.domain.class_var, data.domain.metas ) # domain.addmetas(data.domain.getmetas()) if len(domain.attributes) == 0: message = "No samples with selected sample annotations." stypes = set(s[0] for s in samples) for attr in domain.attributes: attr.attributes = dict( (key, value) for key, value in attr.attributes.items() if key in stypes ) data = Orange.data.Table(domain, data) if message is not None: self.warning(0, message) data_hints.set_hint(data, "taxid", self.currentGds.get("taxid", ""), 10.0) data_hints.set_hint(data, "genesinrows", self.outputRows, 10.0) self.progressBarFinished() data.name = data_name self.send("Expression Data", data) model = self.treeWidget.model().sourceModel() row = self.gds.index(self.currentGds) model.setData(model.index(row, 0), " ", Qt.DisplayRole) self.updateInfo() self.selectionChanged = False def splitterMoved(self, *args): self.splitterSettings = [str(sp.saveState()) for sp in self.splitters] def onDeleteWidget(self): if self._inittask: self._inittask.future().cancel() self._inittask.finished.disconnect(self._initializemodel) if self._datatask: self._datatask.future().cancel() self._datatask.finished.disconnect(self._on_dataready) self._executor.shutdown(wait=False) super(OWGEODatasets, self).onDeleteWidget() def onNameEdited(self): if self.currentGds: gds_id = self.currentGds["dataset_id"] self.datasetNames[gds_id] = unicode(self.nameEdit.text()) self.commitIf()
class ChangedDocumentsListDialog(widgets.dialog.Dialog): def __init__(self): super(ChangedDocumentsListDialog, self).__init__(buttons=('close',)) self.setWindowModality(Qt.NonModal) self.setAttribute(Qt.WA_QuitOnClose, False) layout = QGridLayout(margin=0) self.mainWidget().setLayout(layout) self.tree = QTreeWidget(headerHidden=True, rootIsDecorated=False, columnCount=2, itemsExpandable=False) self.tree.setSelectionMode(QTreeWidget.ExtendedSelection) self.buttonReload = QPushButton() self.buttonReloadAll = QPushButton() self.buttonSave = QPushButton() self.buttonSaveAll = QPushButton() self.buttonShowDiff = QPushButton() self.checkWatchingEnabled = QCheckBox(checked=enabled()) layout.addWidget(self.tree, 0, 0, 6, 1) layout.addWidget(self.buttonReload, 0, 1) layout.addWidget(self.buttonReloadAll, 1, 1) layout.addWidget(self.buttonSave, 2, 1) layout.addWidget(self.buttonSaveAll, 3, 1) layout.addWidget(self.buttonShowDiff, 4, 1) layout.addWidget(self.checkWatchingEnabled, 6, 0, 1, 2) layout.setRowStretch(5, 10) app.documentClosed.connect(self.removeDocument) app.documentSaved.connect(self.removeDocument) app.documentUrlChanged.connect(self.removeDocument) app.documentLoaded.connect(self.removeDocument) self.tree.itemSelectionChanged.connect(self.updateButtons) self.buttonReload.clicked.connect(self.slotButtonReload) self.buttonReloadAll.clicked.connect(self.slotButtonReloadAll) self.buttonSave.clicked.connect(self.slotButtonSave) self.buttonSaveAll.clicked.connect(self.slotButtonSaveAll) self.buttonShowDiff.clicked.connect(self.slotButtonShowDiff) self.checkWatchingEnabled.toggled.connect(setEnabled) app.translateUI(self) qutil.saveDialogSize(self, 'externalchanges/dialog/size', QSize(400, 200)) userguide.addButton(self.buttonBox(), "externalchanges") self.button('close').setFocus() def translateUI(self): self.setWindowTitle(app.caption(_("Modified Files"))) self.setMessage(_( "The following files were modified or deleted by other " "applications:")) self.buttonReload.setText(_("Reload")) self.buttonReload.setToolTip(_( "Reloads the selected documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonReloadAll.setText(_("Reload All")) self.buttonReloadAll.setToolTip(_( "Reloads all externally modified documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonSave.setText(_("Save")) self.buttonSave.setToolTip(_( "Saves the selected documents to disk, overwriting the " "modifications by another program.")) self.buttonSaveAll.setText(_("Save All")) self.buttonSaveAll.setToolTip(_( "Saves all documents to disk, overwriting the modifications by " "another program.")) self.buttonShowDiff.setText(_("Show Difference...")) self.buttonShowDiff.setToolTip(_( "Shows the differences between the current document " "and the file on disk.")) self.checkWatchingEnabled.setText(_( "Enable watching documents for external changes")) self.checkWatchingEnabled.setToolTip(_( "If checked, Frescobaldi will warn you when opened files are " "modified or deleted by other applications.")) def setDocuments(self, documents): """Display the specified documents in the list.""" # clear the treewidget for d in self.tree.invisibleRootItem().takeChildren(): for i in d.takeChildren(): i.doc = None # group the documents by directory dirs = {} for d in documents: path = d.url().toLocalFile() if path: dirname, filename = os.path.split(path) dirs.setdefault(dirname, []).append((filename, d)) for dirname in sorted(dirs, key=util.naturalsort): diritem = QTreeWidgetItem() diritem.setText(0, util.homify(dirname)) self.tree.addTopLevelItem(diritem) diritem.setExpanded(True) diritem.setFlags(Qt.ItemIsEnabled) diritem.setIcon(0, icons.get('folder-open')) for filename, document in sorted(dirs[dirname], key=lambda item: util.naturalsort(item[0])): fileitem = QTreeWidgetItem() diritem.addChild(fileitem) if documentwatcher.DocumentWatcher.instance(document).isdeleted(): itemtext = _("[deleted]") icon = "dialog-error" else: itemtext = _("[modified]") icon = "document-edit" fileitem.setIcon(0, icons.get(icon)) fileitem.setText(0, filename) fileitem.setText(1, itemtext) fileitem.doc = document # select the item if there is only one if len(dirs) == 1 and len(list(dirs.values())[0]) == 1: fileitem.setSelected(True) self.tree.resizeColumnToContents(0) self.tree.resizeColumnToContents(1) self.updateButtons() def removeDocument(self, document): """Remove the specified document from our list.""" for d in range(self.tree.topLevelItemCount()): diritem = self.tree.topLevelItem(d) for f in range(diritem.childCount()): if diritem.child(f).doc is document: i = diritem.takeChild(f) i.doc = None if diritem.childCount() == 0: self.tree.takeTopLevelItem(d) break else: continue break self.updateButtons() # hide if no documents are left if self.tree.topLevelItemCount() == 0: self.hide() def selectedDocuments(self): """Return the selected documents.""" return [i.doc for i in self.tree.selectedItems()] def allDocuments(self): """Return all shown documents.""" return [self.tree.topLevelItem(d).child(f).doc for d in range(self.tree.topLevelItemCount()) for f in range(self.tree.topLevelItem(d).childCount())] def updateButtons(self): """Updates the buttons regarding the selection.""" docs_sel = self.selectedDocuments() docs_all = self.allDocuments() all_deleted_sel = all(documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_sel) all_deleted_all = all(documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_all) self.buttonSave.setEnabled(len(docs_sel) > 0) self.buttonSaveAll.setEnabled(len(docs_all) > 0) self.buttonReload.setEnabled(not all_deleted_sel) self.buttonReloadAll.setEnabled(not all_deleted_all) self.buttonShowDiff.setEnabled(len(docs_sel) == 1 and not all_deleted_sel) def slotButtonReload(self): """Called when the user clicks Reload.""" self.reloadDocuments(self.selectedDocuments()) def slotButtonReloadAll(self): """Called when the user clicks Reload All.""" self.reloadDocuments(self.allDocuments()) def slotButtonSave(self): """Called when the user clicks Save.""" self.saveDocuments(self.selectedDocuments()) def slotButtonSaveAll(self): """Called when the user clicks Save All.""" self.saveDocuments(self.allDocuments()) def reloadDocuments(self, documents): """Used by slotButtonReload and slotButtonReloadAll.""" failures = [] for d in documents: try: d.load(keepUndo=True) except IOError as e: failures.append((d, e)) if failures: msg = _("Could not reload:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format( url = d.url().toLocalFile(), strerror = e.strerror, errno = e.errno) for d, e in failures) QMessageBox.critical(self, app.caption(_("Error")), msg) def saveDocuments(self, documents): """Used by slotButtonSave and slotButtonSaveAll.""" failures = [] for d in documents: try: d.save() except IOError as e: failures.append((d, e)) if failures: msg = _("Could not save:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format( url = d.url().toLocalFile(), strerror = e.strerror, errno = e.errno) for d, e in failures) + "\n\n" + \ _("Please save the document using the \"Save As...\" dialog.", "Please save the documents using the \"Save As...\" dialog.", len(failures)) QMessageBox.critical(self, app.caption(_("Error")), msg) def slotButtonShowDiff(self): """Called when the user clicks Show Difference.""" docs = self.selectedDocuments() or self.allDocuments() if not docs: return d = docs[0] if documentwatcher.DocumentWatcher.instance(d).isdeleted(): return filename = d.url().toLocalFile() try: with open(filename, 'rb') as f: disktext = util.decode(f.read()) except (IOError, OSError): return currenttext = d.toPlainText() html = htmldiff.htmldiff( currenttext, disktext, _("Current Document"), _("Document on Disk"), numlines=5) dlg = widgets.dialog.Dialog(self, buttons=('close',)) view = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap) view.setHtml(html) dlg.setMainWidget(view) dlg.setWindowTitle(app.caption("Differences")) dlg.setMessage(_( "Document: {url}\n" "Difference between the current document and the file on disk:").format( url=filename)) dlg.setWindowModality(Qt.NonModal) dlg.setAttribute(Qt.WA_QuitOnClose, False) dlg.setAttribute(Qt.WA_DeleteOnClose) qutil.saveDialogSize(dlg, "externalchanges/diff/dialog/size", QSize(600, 300)) dlg.show()
class MemUsageDialog(QDialog): def __init__(self, parent=None, update=True): QDialog.__init__(self, parent=parent) layout = QVBoxLayout() self.tree = QTreeWidget() self.tree.setHeaderLabels(["cache", "memory", "roi", "dtype", "type"]) layout.addWidget(self.tree) self.setLayout(layout) self.memMgr = ArrayCacheMemoryMgr.instance self.timer = QTimer(self) if update: self.timer.timeout.connect(self._updateReport) self._updateReport() def _updateReport(self): reports = [] for c in self.memMgr.namedCaches: r = MemInfoNode() try: c.generateReport(r) reports.append(r) except NotImplementedError: warnings.warn('cache operator {} does not implement generateReport()'.format(c)) self._showReports(reports) ''' import pickle f = open("/tmp/reports.pickle",'w') pickle.dump(reports, f) f.close() print "... saved MEM reports to file ..." ''' def _showReports(self, reports): self.tree.clear() root = self.tree.invisibleRootItem() for r in reports: self._showReportsImpl(r, root, 0) def _makeTreeWidgetItem(self, node): l = [] l.append("%r" % node.name) l.append("%1.1f MB" % (node.usedMemory/1024**2.0)) if node.roi is not None: l.append("%r\n%r" % (list(node.roi[0]), list(node.roi[1]))) else: l.append("") if node.dtype is not None: if node.dtype == numpy.float32: l.append("float32") elif node.dtype == numpy.uint8: l.append("uint8") elif node.dtype == numpy.uint32: l.append("uint32") elif node.dtype == numpy.float64: l.append("float64") else: l.append(str(node.dtype)) else: l.append("") t = str(node.type) t = t[len("<type '")+1:-len("'>")] t = t.split(".")[-1] l.append(t) return QTreeWidgetItem(l) def _showReportsImpl(self, node, itm, level): #print " "*level, #print "node", node.name root = self._makeTreeWidgetItem(node) itm.addChild(root) root.setExpanded(True) for c in node.children: self._showReportsImpl(c, root, level+1) def hideEvent(self, event): self.timer.stop() def showEvent(self, show): self.timer.start(5*1000) #update every 5 sec.
class CustomStaff(SymbolManager, QWidget): def __init__(self, dialog): QWidget.__init__(self, dialog) SymbolManager.__init__(self) self.setDefaultSymbolSize(40) self.dialog = dialog self.setLayout(QGridLayout()) self.tree = QTreeWidget() self.stack = QStackedWidget() StackFader(self.stack) self.systems = QSpinBox() newStaves = QVBoxLayout() operations = QHBoxLayout() self.layout().addLayout(newStaves, 0, 0) self.layout().addWidget(self.tree, 0, 1) self.layout().addWidget(self.stack, 0, 2, 1, 2) self.layout().addWidget(self.systems, 1, 3) self.systems.setRange(1, 64) l = QLabel(i18n("Systems per page:")) l.setBuddy(self.systems) self.layout().addWidget(l, 1, 2, Qt.AlignRight) self.layout().addLayout(operations, 1, 1) operations.setSpacing(0) operations.setContentsMargins(0, 0, 0, 0) removeButton = KPushButton(KStandardGuiItem.remove()) removeButton.clicked.connect(self.removeSelectedItems) operations.addWidget(removeButton) upButton = QToolButton() upButton.clicked.connect(self.moveSelectedItemsUp) upButton.setIcon(KIcon("go-up")) operations.addWidget(upButton) downButton = QToolButton() downButton.clicked.connect(self.moveSelectedItemsDown) downButton.setIcon(KIcon("go-down")) operations.addWidget(downButton) newStaves.setSpacing(0) newStaves.setContentsMargins(0, 0, 0, 0) self.tree.setIconSize(QSize(32, 32)) self.tree.setDragDropMode(QTreeWidget.InternalMove) self.tree.headerItem().setHidden(True) self.tree.itemSelectionChanged.connect(self.slotSelectionChanged) for staffType in ( BracketItem, BraceItem, StaffItem, ): b = QPushButton(staffType.name()) b.clicked.connect((lambda t: lambda: self.createItem(t))(staffType)) b.setIconSize(QSize(40, 40)) self.addSymbol(b, staffType.symbol()) newStaves.addWidget(b) def createItem(self, staffType): empty = self.tree.topLevelItemCount() == 0 items = self.tree.selectedItems() if len(items) == 1 and items[0].flags() & Qt.ItemIsDropEnabled: parent = items[0] else: parent = self.tree item = staffType(self, parent) if empty: item.setSelected(True) def slotSelectionChanged(self): items = self.tree.selectedItems() if items: self.stack.setCurrentWidget(items[0].widget) def moveSelectedItemsUp(self): items = self.tree.selectedItems() if items: item = items[0] # currently we support only one selected item parent = item.parent() or self.tree.invisibleRootItem() index = parent.indexOfChild(item) if index > 0: parent.takeChild(index) parent.insertChild(index - 1, item) self.tree.clearSelection() item.setSelected(True) item.setExpanded(True) def moveSelectedItemsDown(self): items = self.tree.selectedItems() if items: item = items[0] # currently we support only one selected item parent = item.parent() or self.tree.invisibleRootItem() index = parent.indexOfChild(item) if index < parent.childCount() - 1: parent.takeChild(index) parent.insertChild(index + 1, item) self.tree.clearSelection() item.setSelected(True) item.setExpanded(True) def removeSelectedItems(self): for item in self.tree.selectedItems(): item.remove() def systemCount(self): return self.systems.value() def name(self): return i18n("Custom Staff") def default(self): while self.tree.topLevelItemCount(): self.tree.topLevelItem(0).remove() self.systems.setValue(4) def items(self): for i in range(self.tree.topLevelItemCount()): yield self.tree.topLevelItem(i) def music(self, layout): music = sum((i.music(layout) for i in self.items()), ['<<']) music.append('>>') return music def staffCount(self): return sum(i.staffCount() for i in self.items())
class RunsDialog(QtHelper.EnhancedQDialog): """ Runs several dialog """ RefreshRepository = pyqtSignal(str) def __init__(self, dialogName, parent = None, iRepo=None, lRepo=None, rRepo=None): """ Constructor """ QtHelper.EnhancedQDialog.__init__(self, parent) self.name = self.tr("Prepare a group of runs") self.projectReady = False self.iRepo = iRepo self.lRepo = lRepo self.rRepo = rRepo self.createDialog() self.createConnections() def createDialog(self): """ Create qt dialog """ self.setWindowTitle( self.name ) mainLayout = QHBoxLayout() layoutTests = QHBoxLayout() layoutRepoTest = QVBoxLayout() self.prjCombo = QComboBox(self) self.prjCombo.setEnabled(False) self.repoTests = QTreeWidget(self) self.repoTests.setFrameShape(QFrame.NoFrame) if USE_PYQT5: self.repoTests.header().setSectionResizeMode(QHeaderView.Stretch) else: self.repoTests.header().setResizeMode(QHeaderView.Stretch) self.repoTests.setHeaderHidden(True) self.repoTests.setContextMenuPolicy(Qt.CustomContextMenu) self.repoTests.setIndentation(10) layoutRepoTest.addWidget(self.prjCombo) layoutRepoTest.addWidget(self.repoTests) self.testsList = QListWidget(self) layoutTests.addLayout( layoutRepoTest ) layoutTests.addWidget( self.testsList ) mainLayout.addLayout( layoutTests ) buttonLayout = QVBoxLayout() self.okButton = QPushButton(self.tr("Execute All"), self) self.okButton.setEnabled(False) self.cancelButton = QPushButton(self.tr("Cancel"), self) self.upButton = QPushButton(self.tr("UP"), self) self.upButton.setEnabled(False) self.downButton = QPushButton(self.tr("DOWN"), self) self.downButton.setEnabled(False) self.clearButton = QPushButton(self.tr("Remove All"), self) self.delButton = QPushButton(self.tr("Remove"), self) self.delButton.setEnabled(False) self.runSimultaneous = QCheckBox(self.tr("Simultaneous Run")) self.schedImmed = QRadioButton(self.tr("Run Immediately")) self.schedImmed.setChecked(True) self.schedAt = QRadioButton(self.tr("Run At:")) self.schedAtDateTimeEdit = QDateTimeEdit(QDateTime.currentDateTime()) self.schedAtDateTimeEdit.setEnabled(False) buttonLayout.addWidget(self.okButton) buttonLayout.addWidget(self.runSimultaneous) buttonLayout.addWidget(self.schedImmed) buttonLayout.addWidget(self.schedAt) buttonLayout.addWidget(self.schedAtDateTimeEdit) buttonLayout.addWidget( self.upButton ) buttonLayout.addWidget( self.downButton ) buttonLayout.addWidget( self.delButton ) buttonLayout.addWidget( self.clearButton ) buttonLayout.addWidget(self.cancelButton) mainLayout.addLayout(buttonLayout) self.setMinimumHeight(400) self.setMinimumWidth(750) self.setLayout(mainLayout) def initProjects(self, projects=[], defaultProject=1): """ Initialize projects """ # init date and time self.schedAtDateTimeEdit.setDateTime(QDateTime.currentDateTime()) self.projectReady = False self.repoTests.clear() self.prjCombo.clear() self.testsList.clear() self.prjCombo.setEnabled(True) # insert data pname = '' for p in projects: self.prjCombo.addItem ( p['name'] ) if defaultProject == p['project_id']: pname = p['name'] for i in xrange(self.prjCombo.count()): item_text = self.prjCombo.itemText(i) if str(pname) == str(item_text): self.prjCombo.setCurrentIndex(i) self.projectReady = True self.RefreshRepository.emit(pname) def initializeTests(self, listing): """ Initialize tests """ self.repoTests.clear() self.testRoot = self.rRepo.Item(repo = self.iRepo.remote(), parent = self.repoTests, txt = "Root", type = QTreeWidgetItem.UserType+10, isRoot = True ) self.testRoot.setSelected(True) self.createRepository(listing=listing, parent=self.testRoot,fileincluded=True) self.repoTests.sortItems(0, Qt.AscendingOrder) self.hideItems(hideTsx=False, hideTpx=False, hideTcx=True, hideTdx=True, hideTxt=True, hidePy=True, hideTux=False, hidePng=True, hideTgx=False, hideTax=False) def createRepository(self, listing, parent, fileincluded=True): """ Create repository @param listing: @type listing: list @param parent: @type parent: @param fileincluded: @type fileincluded: boolean """ try: for dct in listing: if dct["type"] == "folder": item = self.rRepo.Item(repo = self.iRepo.remote(), parent = parent, txt = dct["name"], propertiesFile=dct ) self.createRepository( dct["content"] , item, fileincluded ) else: if fileincluded: if dct["type"] == "file": pname = self.iRepo.remote().getProjectName(dct["project"]) # {'modification': 1342259500, 'type': 'file', 'name': '__init__.py', 'size': '562 } item = self.rRepo.Item(repo = self.iRepo.remote(), parent = parent, txt = dct["name"] , propertiesFile=dct, type = QTreeWidgetItem.UserType+0, projectId=dct["project"], projectName=pname ) except Exception as e: self.error( "unable to create tree for runs: %s" % e ) def onProjectChanged(self, projectItem): """ Called when the project changed on the combo box """ if self.projectReady: item_text = self.prjCombo.itemText(projectItem) self.RefreshRepository.emit(item_text) def createConnections (self): """ create qt connections * ok * cancel """ self.prjCombo.currentIndexChanged.connect(self.onProjectChanged) self.okButton.clicked.connect( self.acceptClicked ) self.cancelButton.clicked.connect( self.reject ) self.upButton.clicked.connect(self.upTest) self.downButton.clicked.connect(self.downTest) self.clearButton.clicked.connect(self.clearList) self.delButton.clicked.connect(self.delTest) self.testsList.itemClicked.connect(self.onItemSelected) self.testsList.itemSelectionChanged.connect(self.onItemSelectionChanged) self.schedAt.toggled.connect(self.onSchedAtActivated) self.repoTests.itemDoubleClicked.connect( self.onTestDoucleClicked ) def onSchedAtActivated(self, toggled): """ On sched at button activated """ if toggled: self.schedAtDateTimeEdit.setEnabled(True) else: self.schedAtDateTimeEdit.setEnabled(False) def onItemSelectionChanged(self): """ Called on item selection changed """ self.onItemSelected(itm=None) def onItemSelected(self, itm): """ Call on item selected """ selectedItems = self.testsList.selectedItems() if len(selectedItems): self.delButton.setEnabled(True) self.upButton.setEnabled(True) self.downButton.setEnabled(True) else: self.delButton.setEnabled(False) self.upButton.setEnabled(False) self.downButton.setEnabled(False) if not self.testsList.count(): self.okButton.setEnabled(False) def upTest(self): """ Up test """ currentRow = self.testsList.currentRow() currentItem = self.testsList.takeItem(currentRow) self.testsList.insertItem(currentRow - 1, currentItem) def downTest(self): """ Down test """ currentRow = self.testsList.currentRow() currentItem = self.testsList.takeItem(currentRow) self.testsList.insertItem(currentRow + 1, currentItem) def delTest(self): """ Del test """ currentRow = self.testsList.currentRow() currentItem = self.testsList.takeItem(currentRow) def clearList(self): """ Clear test """ self.testsList.clear() self.delButton.setEnabled(False) self.upButton.setEnabled(False) self.downButton.setEnabled(False) self.okButton.setEnabled(False) def iterateTree(self, item, hideTsx, hideTpx, hideTcx, hideTdx, hideTxt, hidePy, hideTux, hidePng, hideTgx, hideTax): """ Iterate tree """ child_count = item.childCount() for i in range(child_count): subitem = item.child(i) subchild_count = subitem.childCount() if subchild_count > 0: self.iterateTree(item=subitem, hideTsx=hideTsx, hideTpx=hideTpx, hideTcx=hideTcx, hideTdx=hideTdx, hideTxt=hideTxt, hidePy=hidePy, hideTux=hideTux, hidePng=hidePng, hideTgx=hideTgx, hideTax=hideTax) else: if hideTux and subitem.getExtension() == self.rRepo.EXTENSION_TUX: subitem.setHidden (True) elif hideTpx and subitem.getExtension() == self.rRepo.EXTENSION_TPX: subitem.setHidden (True) elif hideTgx and subitem.getExtension() == self.rRepo.EXTENSION_TGX: subitem.setHidden (True) elif hideTcx and subitem.getExtension() == self.rRepo.EXTENSION_TCX: subitem.setHidden (True) elif hideTsx and subitem.getExtension() == self.rRepo.EXTENSION_TSX: subitem.setHidden (True) elif hideTdx and subitem.getExtension() == self.rRepo.EXTENSION_TDX: subitem.setHidden (True) elif hideTxt and subitem.getExtension() == self.rRepo.EXTENSION_TXT: subitem.setHidden (True) elif hidePy and subitem.getExtension() == self.rRepo.EXTENSION_PY: subitem.setHidden (True) elif hidePng and subitem.getExtension() == self.rRepo.EXTENSION_PNG: subitem.setHidden (True) elif hideTax and subitem.getExtension() == self.rRepo.EXTENSION_TAx: subitem.setHidden (True) else: subitem.setHidden(False) def hideItems(self, hideTsx=False, hideTpx=False, hideTcx=False, hideTdx=False, hideTxt=False, hidePy=False, hideTux=False, hidePng=False, hideTgx=False, hideTax=False): """ Hide items """ root = self.repoTests.invisibleRootItem() self.iterateTree(item=root, hideTsx=hideTsx, hideTpx=hideTpx, hideTcx=hideTcx, hideTdx=hideTdx, hideTxt=hideTxt, hidePy=hidePy, hideTux=hideTux, hidePng=hidePng, hideTgx=hideTgx, hideTax=hideTax) def onTestDoucleClicked(self, testItem): """ On tests double clicked """ if testItem.type() != QTreeWidgetItem.UserType+0: return self.okButton.setEnabled(True) currentProject = self.prjCombo.currentText() testName = "%s:%s" % (str(currentProject),testItem.getPath(withFileName = True)) testItem = QListWidgetItem(testName ) if testName.endswith(self.rRepo.EXTENSION_TUX): testItem.setIcon(QIcon(":/tux.png")) if testName.endswith(self.rRepo.EXTENSION_TSX): testItem.setIcon(QIcon(":/tsx.png")) if testName.endswith(self.rRepo.EXTENSION_TPX): testItem.setIcon(QIcon(":/tpx.png")) if testName.endswith(self.rRepo.EXTENSION_TGX): testItem.setIcon(QIcon(":/tgx.png")) if testName.endswith(self.rRepo.EXTENSION_TAX): testItem.setIcon(QIcon(":/tax.png")) self.testsList.addItem( testItem ) def acceptClicked (self): """ Called on accept button """ self.accept() def getTests(self): """ Returns all tests in the list """ tests = [] for i in xrange(self.testsList.count()): testItem = self.testsList.item(i) tests.append( str(testItem.text()) ) runSimultaneous = False if self.runSimultaneous.isChecked(): runSimultaneous = True if self.schedImmed.isChecked(): runAt = (0,0,0,0,0,0) return (tests, False, runAt, runSimultaneous) else: pydt = self.schedAtDateTimeEdit.dateTime().toPyDateTime() runAt = (pydt.year, pydt.month, pydt.day, pydt.hour, pydt.minute, pydt.second) return (tests, True, runAt, runSimultaneous)
class SettingsWindow(QWidget): min_max_changed = pyqtSignal(tuple, str) indicators_changed = pyqtSignal(bool) interpolation_changed = pyqtSignal(str) samples_unit_changed = pyqtSignal(str) def __init__(self, context, parent=None): """ :type context: segyviewlib.SliceViewContext :type parent: QObject """ QWidget.__init__(self, parent, Qt.WindowStaysOnTopHint | Qt.Window) self.setVisible(False) self._context = context self._context.context_changed.connect(self._settings_changed) self._context.data_changed.connect(self._settings_changed) self._context.data_source_changed.connect(self._settings_changed) f_layout = QFormLayout() self._iline_count = QLabel("") self._xline_count = QLabel("") self._offset_count = QLabel("") self._sample_count = QLabel("") self._minimum_value = QLabel("") self._maximum_value = QLabel("") f_layout.addRow("Inline Count:", self._iline_count) f_layout.addRow("Crossline Count:", self._xline_count) f_layout.addRow("Offset Count:", self._offset_count) f_layout.addRow("Sample Count:", self._sample_count) if self._context._has_data: f_layout.addRow("Minimum Value:", self._minimum_value) f_layout.addRow("Maximum Value:", self._maximum_value) # iline self._il_ctrl = IndexController(parent=self, context=self._context, slice_direction_index_source=SliceDirection.inline) self._il_ctrl.index_changed.connect(self._index_changed_fn(SliceDirection.inline)) self._il_ctrl.min_max_changed.connect(self.iline_limits_changed) # xline self._xl_ctrl = IndexController(parent=self, context=self._context, slice_direction_index_source=SliceDirection.crossline) self._xl_ctrl.index_changed.connect(self._index_changed_fn(SliceDirection.crossline)) self._xl_ctrl.min_max_changed.connect(self.xline_limits_changed) # depth self._depth_ctrl = IndexController(parent=self, context=self._context, slice_direction_index_source=SliceDirection.depth) self._depth_ctrl.index_changed.connect(self._index_changed_fn(SliceDirection.depth)) self._depth_ctrl.min_max_changed.connect(self.depth_limits_changed) # sample self._sample_ctrl = SampleScaleController(self) self._sample_ctrl.min_max_changed.connect(self.sample_limits_changed) self._symmetric_scale = QCheckBox() self._symmetric_scale.toggled.connect(self._context.set_symmetric_scale) self._samples_unit = QComboBox() self._samples_unit.addItems(['Time (ms)', 'Depth (m)']) self._samples_unit.currentIndexChanged[str].connect(self.samples_unit) # view self._view_label = QLabel("") self._view_label.setDisabled(True) self._indicator_visibility = QCheckBox() self._indicator_visibility.toggled.connect(self._show_indicators) self._indicator_visibility.toggled.connect(lambda: self._set_view_label(self._indicator_visibility.isChecked())) self._interpolation_combo = QComboBox() self._interpolations_names = ['nearest', 'catrom', 'sinc'] self._interpolation_combo.addItems(self._interpolations_names) self._interpolation_combo.currentIndexChanged.connect(self._interpolation_changed) # plot export settings self._plt_settings_wdgt = PlotExportSettingsWidget(self, parent._slice_view_widget, self._context) # define tree layout tree_def = {"": [ {"Inline": [{"set_expanded": True}, {"": self._align(self._il_ctrl.current_index_label)}, {"Inline:": self._align(self._il_ctrl.index_widget)}, {"Minimum:": self._align(self._il_ctrl.min_spinbox, self._il_ctrl.min_checkbox)}, {"Maximum:": self._align(self._il_ctrl.max_spinbox, self._il_ctrl.max_checkbox)} ] }, {"Crossline": [{"set_expanded": True}, {"": self._align(self._xl_ctrl.current_index_label)}, {"Crossline:": self._align(self._xl_ctrl.index_widget)}, {"Minimum:": self._align(self._xl_ctrl.min_spinbox, self._xl_ctrl.min_checkbox)}, {"Maximum:": self._align(self._xl_ctrl.max_spinbox, self._xl_ctrl.max_checkbox)} ] }, {"Depth": [{"set_expanded": True}, {"": self._align(self._depth_ctrl.current_index_label)}, {"Depth:": self._align(self._depth_ctrl.index_widget)}, {"Minimum:": self._align(self._depth_ctrl.min_spinbox, self._depth_ctrl.min_checkbox)}, {"Maximum:": self._align(self._depth_ctrl.max_spinbox, self._depth_ctrl.max_checkbox)}, {"Type": self._align(self._samples_unit)} ] }, {"Color Scale": [ {"Custom min.:": self._align(self._sample_ctrl.min_spinbox, self._sample_ctrl.min_checkbox)}, {"Custom max.:": self._align(self._sample_ctrl.max_spinbox, self._sample_ctrl.max_checkbox)}, {"Symmetric scale:": self._align(self._symmetric_scale)} ] }, {"View": [{"": self._align(self._view_label)}, {"Show Indicators:": self._align(self._indicator_visibility)}, {"Interpolation Type:": self._align(self._interpolation_combo)} ] }, {"Plot export dimensions": [ {"": self._align(self._plt_settings_wdgt.label)}, {"Fixed size": self._align(self._plt_settings_wdgt.checkbox)}, {"Width:": self._align(self._plt_settings_wdgt.width_spinbox)}, {"Height:": self._align(self._plt_settings_wdgt.height_spinbox)}, {"Units:": self._align(self._plt_settings_wdgt.units_combobox)} ] } ]} # setup the menu/navigation tree widget self._tree = QTreeWidget(self) self._tree.setHeaderHidden(True) self._tree.setColumnCount(2) self._tree.setColumnWidth(0, 140) self._tree.setColumnWidth(1, 180) self._build_tree(self._tree, tree_def, self._tree.invisibleRootItem()) # layout vertical_layout = QVBoxLayout() button_layout = QHBoxLayout() button_layout.setContentsMargins(0, 0, 0, 0) close_button = QPushButton("Close") close_button.clicked.connect(self.close) button_layout.addStretch() button_layout.addWidget(close_button) vertical_layout.addLayout(f_layout, 0) vertical_layout.addStretch() vertical_layout.addWidget(self._tree, 1) vertical_layout.addStretch() vertical_layout.addLayout(button_layout, 0) self.setLayout(vertical_layout) self.setMinimumSize(390, 740) @property def qtree(self): """ :rtype: QTreeWidget """ return self._tree @staticmethod def _align(widget, checkbox=None): l = QHBoxLayout() if checkbox is not None: checkbox.setMaximumWidth(23) l.addWidget(checkbox, 0) else: l.addSpacing(25) l.addStretch(0.5) if widget is not None: widget.setMinimumWidth(180) widget.setMaximumWidth(180) l.addWidget(widget) else: l.addSpacing(180) l.setContentsMargins(0, 0, 0, 0) l.addStretch(1) w = QWidget() w.setContentsMargins(0, 2, 0, 2) w.setLayout(l) return w def samples_unit(self, val): self._context.samples_unit = val self.samples_unit_changed.emit(val) def _create_user_value(self): layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) def _build_tree(self, tree_wdgt, tree_def, root): parent, children = tree_def.items()[0] # empty label /parent is a special case: either inline with the previous, or skip if parent == "": if isinstance(children, QWidget): item = root tree_wdgt.setItemWidget(item, 1, children) elif isinstance(children, list): for c in children: self._build_tree(tree_wdgt, c, root) elif parent == "set_expanded": # a configuration item for the current root root.setExpanded(children) else: item = QTreeWidgetItem(root) item.setText(0, parent) if isinstance(children, list): for c in children: self._build_tree(tree_wdgt, c, item) else: tree_wdgt.setItemWidget(item, 1, children) def add_empty_row(self, layout, legend=""): layout.addRow(legend, QLabel()) def _settings_changed(self): ctx = self._context self._indicator_visibility.setChecked(ctx.indicators) index = self._interpolations_names.index(ctx.interpolation) self._interpolation_combo.setCurrentIndex(index) self._symmetric_scale.setChecked(ctx.symmetric_scale) ilines, xlines, offsets, samples = ctx.slice_data_source().dims() self._iline_count.setText("%d" % ilines) self._xline_count.setText("%d" % xlines) self._offset_count.setText("%d" % offsets) self._sample_count.setText("%d" % samples) if ctx._has_data: self._minimum_value.setText("%f" % ctx.global_minimum) self._maximum_value.setText("%f" % ctx.global_maximum) indexes = ctx.slice_data_source().indexes_for_direction(SliceDirection.inline).tolist() index = ctx.index_for_direction(SliceDirection.inline) self._il_ctrl.update_view(indexes, index) indexes = ctx.slice_data_source().indexes_for_direction(SliceDirection.crossline).tolist() index = ctx.index_for_direction(SliceDirection.crossline) self._xl_ctrl.update_view(indexes, index) indexes = ctx.slice_data_source().indexes_for_direction(SliceDirection.depth).tolist() index = ctx.index_for_direction(SliceDirection.depth) self._depth_ctrl.update_view(indexes, index) index = self._samples_unit.findText(ctx.samples_unit) if index != -1: self._samples_unit.setCurrentIndex(index) def _set_view_label(self, indicator_on): self._view_label.setText("indicators {0}".format("on" if indicator_on else "off")) def _show_indicators(self, visible): self._context.show_indicators(visible) self.indicators_changed.emit(visible) def _interpolation_changed(self, index): interpolation_name = str(self._interpolation_combo.itemText(index)) self._context.set_interpolation(interpolation_name) self.interpolation_changed.emit(interpolation_name) def _index_changed_fn(self, direction): def fn(value): self._context.update_index_for_direction(direction, value) return fn def sample_limits_changed(self, values): self._context.set_user_values(*values) def depth_limits_changed(self, values): if self._context.has_data: min, max = values self._context.set_y_view_limits(SliceDirection.crossline, min, max) self._context.set_y_view_limits(SliceDirection.inline, min, max) else: self.min_max_changed.emit(values, 'depth') def iline_limits_changed(self, values): if self._context.has_data: min, max = values self._context.set_x_view_limits(SliceDirection.crossline, min, max) self._context.set_x_view_limits(SliceDirection.depth, min, max) else: self.min_max_changed.emit(values, 'iline') def xline_limits_changed(self, values): if self._context.has_data: min, max = values self._context.set_x_view_limits(SliceDirection.inline, min, max) self._context.set_y_view_limits(SliceDirection.depth, min, max) else: self.min_max_changed.emit(values, 'xline')
class MemUsageDialog(QDialog): def __init__(self, parent=None, update=True): QDialog.__init__(self, parent=parent) layout = QVBoxLayout() self.tree = QTreeWidget() self.tree.setHeaderLabels(["cache", "memory", "roi", "dtype", "type"]) layout.addWidget(self.tree) self.setLayout(layout) self.memMgr = ArrayCacheMemoryMgr.instance self.timer = QTimer(self) if update: self.timer.timeout.connect(self._updateReport) self._updateReport() def _updateReport(self): reports = [] for c in self.memMgr.namedCaches: r = MemInfoNode() try: c.generateReport(r) reports.append(r) except NotImplementedError: warnings.warn("cache operator {} does not implement generateReport()".format(c)) self._showReports(reports) """ import pickle f = open("/tmp/reports.pickle",'w') pickle.dump(reports, f) f.close() print "... saved MEM reports to file ..." """ def _showReports(self, reports): self.tree.clear() root = self.tree.invisibleRootItem() for r in reports: self._showReportsImpl(r, root, 0) def _makeTreeWidgetItem(self, node): l = [] l.append("%r" % node.name) l.append("%1.1f MB" % (node.usedMemory / 1024 ** 2.0)) if node.roi is not None: l.append("%r\n%r" % (list(node.roi[0]), list(node.roi[1]))) else: l.append("") if node.dtype is not None: if node.dtype == numpy.float32: l.append("float32") elif node.dtype == numpy.uint8: l.append("uint8") elif node.dtype == numpy.uint32: l.append("uint32") elif node.dtype == numpy.float64: l.append("float64") else: l.append(str(node.dtype)) else: l.append("") t = str(node.type) t = t[len("<type '") + 1 : -len("'>")] t = t.split(".")[-1] l.append(t) return QTreeWidgetItem(l) def _showReportsImpl(self, node, itm, level): # print " "*level, # print "node", node.name root = self._makeTreeWidgetItem(node) itm.addChild(root) root.setExpanded(True) for c in node.children: self._showReportsImpl(c, root, level + 1) def hideEvent(self, event): self.timer.stop() def showEvent(self, show): self.timer.start(5 * 1000) # update every 5 sec.
class OWItemsets(widget.OWWidget): name = "Frequent Itemsets" description = "Explore sets of items that frequently appear together." icon = "icons/FrequentItemsets.svg" priority = 10 inputs = [("Data", Table, "set_data")] outputs = [(Output.DATA, Table)] minSupport = settings.Setting(30) maxItemsets = settings.Setting(10000) filterSearch = settings.Setting(True) autoFind = settings.Setting(False) autoSend = settings.Setting(True) filterKeywords = settings.Setting("") filterMinItems = settings.Setting(1) filterMaxItems = settings.Setting(10000) UserAdviceMessages = [ widget.Message( "Itemset are listed in item-sorted order, i.e. " "an itemset containing A and B is only listed once, as " "A > B (and not also B > A).", "itemsets-order", widget.Message.Warning, ), widget.Message( "To select all the itemsets that are descendants of " "(include) some item X (i.e. the whole subtree), you " "can fold the subtree at that item and then select it.", "itemsets-order", widget.Message.Information, ), ] def __init__(self): self._is_running = False self.isRegexMatch = lambda x: True self.tree = QTreeWidget( self.mainArea, columnCount=2, allColumnsShowFocus=True, alternatingRowColors=True, selectionMode=QTreeWidget.ExtendedSelection, uniformRowHeights=True, ) self.tree.setHeaderLabels(["Itemsets", "Support", "%"]) self.tree.header().setStretchLastSection(True) self.tree.itemSelectionChanged.connect(self.selectionChanged) self.mainArea.layout().addWidget(self.tree) box = gui.widgetBox(self.controlArea, "Info") self.nItemsets = self.nSelectedExamples = self.nSelectedItemsets = "" gui.label(box, self, "Number of itemsets: %(nItemsets)s") gui.label(box, self, "Selected itemsets: %(nSelectedItemsets)s") gui.label(box, self, "Selected examples: %(nSelectedExamples)s") hbox = gui.widgetBox(box, orientation="horizontal") gui.button(hbox, self, "Expand all", callback=self.tree.expandAll) gui.button(hbox, self, "Collapse all", callback=self.tree.collapseAll) box = gui.widgetBox(self.controlArea, "Find itemsets") gui.valueSlider( box, self, "minSupport", values=[0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5] + list(range(1, 101)), label="Minimal support:", labelFormat="%g%%", callback=lambda: self.find_itemsets(), ) gui.hSlider( box, self, "maxItemsets", minValue=10000, maxValue=100000, step=10000, label="Max. number of itemsets:", labelFormat="%d", callback=lambda: self.find_itemsets(), ) self.button = gui.auto_commit(box, self, "autoFind", "Find itemsets", commit=self.find_itemsets) box = gui.widgetBox(self.controlArea, "Filter itemsets") gui.lineEdit( box, self, "filterKeywords", "Contains:", callback=self.filter_change, orientation="horizontal", tooltip="A comma or space-separated list of regular " "expressions.", ) hbox = gui.widgetBox(box, orientation="horizontal") gui.spin(hbox, self, "filterMinItems", 1, 998, label="Min. items:", callback=self.filter_change) gui.spin(hbox, self, "filterMaxItems", 2, 999, label="Max. items:", callback=self.filter_change) gui.checkBox( box, self, "filterSearch", label="Apply these filters in search", tooltip="If checked, the itemsets are filtered according " "to these filter conditions already in the search " "phase. \nIf unchecked, the only filters applied " "during search are the ones above, " "and the itemsets are \nfiltered afterwards only for " "display, i.e. only the matching itemsets are shown.", ) gui.rubber(hbox) gui.rubber(self.controlArea) gui.auto_commit(self.controlArea, self, "autoSend", "Send selection") self.filter_change() ITEM_DATA_ROLE = Qt.UserRole + 1 def selectionChanged(self): X = self.X mapping = self.onehot_mapping instances = set() where = np.where def whole_subtree(node): yield node for i in range(node.childCount()): yield from whole_subtree(node.child(i)) def itemset(node): while node: yield node.data(0, self.ITEM_DATA_ROLE) node = node.parent() def selection_ranges(node): n_children = node.childCount() if n_children: yield (self.tree.indexFromItem(node.child(0)), self.tree.indexFromItem(node.child(n_children - 1))) for i in range(n_children): yield from selection_ranges(node.child(i)) nSelectedItemsets = 0 item_selection = QItemSelection() for node in self.tree.selectedItems(): nodes = (node,) if node.isExpanded() else whole_subtree(node) if not node.isExpanded(): for srange in selection_ranges(node): item_selection.select(*srange) for node in nodes: nSelectedItemsets += 1 cols, vals = zip(*(mapping[i] for i in itemset(node))) if issparse(X): rows = (len(cols) == np.bincount((X[:, cols] != 0).indices, minlength=X.shape[0])).nonzero()[0] else: rows = where((X[:, cols] == vals).all(axis=1))[0] instances.update(rows) self.tree.itemSelectionChanged.disconnect(self.selectionChanged) self.tree.selectionModel().select(item_selection, QItemSelectionModel.Select | QItemSelectionModel.Rows) self.tree.itemSelectionChanged.connect(self.selectionChanged) self.nSelectedExamples = len(instances) self.nSelectedItemsets = nSelectedItemsets self.output = self.data[sorted(instances)] or None self.commit() def commit(self): self.send(Output.DATA, self.output) def filter_change(self): self.warning(9) try: isRegexMatch = self.isRegexMatch = re.compile( "|".join(i.strip() for i in re.split("(,|\s)+", self.filterKeywords.strip()) if i.strip()), re.IGNORECASE, ).search except Exception as e: self.warning(9, "Error in regular expression: {}".format(e.args[0])) isRegexMatch = self.isRegexMatch = lambda x: True def hide(node, depth, has_kw): if not has_kw: has_kw = isRegexMatch(node.text(0)) hidden = ( sum(hide(node.child(i), depth + 1, has_kw) for i in range(node.childCount())) == node.childCount() if node.childCount() else (not has_kw or not self.filterMinItems <= depth <= self.filterMaxItems) ) node.setHidden(hidden) return hidden hide(self.tree.invisibleRootItem(), 0, False) class TreeWidgetItem(QTreeWidgetItem): def data(self, column, role): """Construct lazy tooltips""" if role != Qt.ToolTipRole: return super().data(column, role) tooltip = [] while self: tooltip.append(self.text(0)) self = self.parent() return " ".join(reversed(tooltip)) def find_itemsets(self): if self.data is None: return if self._is_running: return self._is_running = True data = self.data self.tree.clear() self.tree.setUpdatesEnabled(False) self.tree.blockSignals(True) class ItemDict(dict): def __init__(self, item): self.item = item top = ItemDict(self.tree.invisibleRootItem()) X, mapping = OneHot.encode(data) self.onehot_mapping = mapping ITEM_FMT = "{}" if issparse(data.X) else "{}={}" names = { item: ITEM_FMT.format(var.name, val) for item, var, val in OneHot.decode(mapping.keys(), data, mapping) } nItemsets = 0 filterSearch = self.filterSearch filterMinItems, filterMaxItems = self.filterMinItems, self.filterMaxItems isRegexMatch = self.isRegexMatch # Find itemsets and populate the TreeView with self.progressBar(self.maxItemsets + 1) as progress: for itemset, support in frequent_itemsets(X, self.minSupport / 100): if filterSearch and not filterMinItems <= len(itemset) <= filterMaxItems: continue parent = top first_new_item = None itemset_matches_filter = False for item in sorted(itemset): name = names[item] if filterSearch and not itemset_matches_filter: itemset_matches_filter = isRegexMatch(name) child = parent.get(name) if child is None: try: wi = self.TreeWidgetItem( parent.item, [name, str(support), "{:.4g}".format(100 * support / len(data))] ) except RuntimeError: # FIXME: When autoFind was in effect and the support # slider was moved, this line excepted with: # RuntimeError: wrapped C/C++ object of type # TreeWidgetItem has been deleted return wi.setData(0, self.ITEM_DATA_ROLE, item) child = parent[name] = ItemDict(wi) if first_new_item is None: first_new_item = (parent, name) parent = child if filterSearch and not itemset_matches_filter: parent, name = first_new_item parent.item.removeChild(parent[name].item) del parent[name].item del parent[name] else: nItemsets += 1 progress.advance() if nItemsets >= self.maxItemsets: break if not filterSearch: self.filter_change() self.nItemsets = nItemsets self.nSelectedItemsets = 0 self.nSelectedExamples = 0 self.tree.expandAll() for i in range(self.tree.columnCount()): self.tree.resizeColumnToContents(i) self.tree.setUpdatesEnabled(True) self.tree.blockSignals(False) self._is_running = False def set_data(self, data): self.data = data is_error = False if data is not None: self.warning(0) self.error(1) self.button.setDisabled(False) self.X = data.X if issparse(data.X): self.X = data.X.tocsc() else: if not data.domain.has_discrete_attributes(): self.error(1, "Discrete features required but data has none.") is_error = True self.button.setDisabled(True) elif data.domain.has_continuous_attributes(): self.warning(0, "Data has continuous attributes which will be skipped.") else: self.output = None self.commit() if self.autoFind and not is_error: self.find_itemsets()
class Shortcuts(preferences.Page): def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton(icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager(win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = allactions.keys() def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelelator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0) def items(self): """Yield all the items in the actions tree.""" def children(item): for i in range(item.childCount()): c = item.child(i) if c.childCount(): for c1 in children(c): yield c1 else: yield c for c in children(self.tree.invisibleRootItem()): yield c def saveSettings(self): self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts") for item in self.items(): for scheme in self.scheme.schemes(): item.save(scheme) item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def loadSettings(self): self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes") # clear the settings in all the items for item in self.items(): item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def slotSchemeChanged(self): """Called when the Scheme combobox is changed by the user.""" for item in self.items(): item.switchScheme(self.scheme.currentScheme()) def slotCurrentItemChanged(self, item): if isinstance(item, ShortcutItem): self.edit.setText( _("&Edit Shortcut for \"{name}\"").format(name=item.text(0))) self.edit.setEnabled(True) global _lastaction _lastaction = item.name else: self.edit.setText(_("(no shortcut)")) self.edit.setEnabled(False) def editCurrentItem(self): item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return try: dlg = self._editdialog except AttributeError: dlg = self._editdialog = ShortcutEditDialog(self) scheme = self.scheme.currentScheme() action = item.action(scheme) default = item.defaultShortcuts() if dlg.editAction(action, default): shortcuts = action.shortcuts() # check for conflicts conflicting = [] for i in self.items(): if i is not item: for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts): if s1.matches(s2) or s2.matches(s1): conflicting.append(i) if conflicting: # show a question dialog msg = [_("This shortcut conflicts with the following command:", "This shortcut conflicts with the following commands:", len(conflicting))] msg.append('<br/>'.join(i.text(0) for i in conflicting)) msg.append(_("Remove the shortcut from that command?", "Remove the shortcut from those commands?", len(conflicting))) msg = '<p>{0}</p>'.format('</p><p>'.join(msg)) res = QMessageBox.warning(self, _("Shortcut Conflict"), msg, QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if res == QMessageBox.Yes: # remove from conflicting for i in conflicting: l = i.shortcuts(scheme) for s1 in list(l): # copy for s2 in shortcuts: if s1.matches(s2) or s2.matches(s1): l.remove(s1) i.setShortcuts(l, scheme) elif res == QMessageBox.No: # remove from ourselves for i in conflicting: for s1 in list(shortcuts): # copy for s2 in i.shortcuts(scheme): if s1.matches(s2) or s2.matches(s1): shortcuts.remove(s1) else: return # cancelled # store the shortcut item.setShortcuts(shortcuts, scheme) self.changed.emit()
class SetupDBPage(QWizardPage): treeViewSetting = config['treeViewSet'] def __init__(self, parent=None): super(SetupDBPage, self).__init__(parent) self.setTitle(QApplication.translate("SetupDBPage", 'Importované tabulky a sloupce', None, QApplication.UnicodeUTF8)) self.treeWidget = QTreeWidget() self.treeWidget.setHeaderHidden(True) self.addItems(self.treeWidget.invisibleRootItem()) self.treeWidget.itemChanged.connect (self.checkBoxDriver) self.treeWidget.itemChanged.connect (self.rewriteConfig) layout = QVBoxLayout() layout.addWidget(self.treeWidget) self.setLayout(layout) def addItems(self, parent): column = 0 names = self.treeViewSetting.keys() for name in names: if 'Root' not in name: nameParent = name statusParent = self.treeViewSetting[name + 'Root'] nameParent = self.addParent(parent, column, str(name), 'data ' + str(name), statusParent) atribs = self.treeViewSetting[name].keys() for atr in atribs: statusAtr = self.treeViewSetting[name][atr] self.addChild(nameParent, column,str(atr),'data ' + str(atr), statusAtr) def addParent(self, parent, column, title, data, status): item = QTreeWidgetItem(parent, [title]) item.setData(column, Qt.UserRole, data) item.setChildIndicatorPolicy(QTreeWidgetItem.ShowIndicator) item.setCheckState (column, self.getCheckStatus(status)) item.setExpanded (False) return item def addChild(self, parent, column, title, data, status): item = QTreeWidgetItem(parent, [title]) item.setData(column, Qt.UserRole, data) item.setCheckState (column, self.getCheckStatus(status)) return item def getCheckStatus(self,status): if status == 'True': return Qt.Checked if status == 'Semi': return Qt.PartiallyChecked if status == 'False': return Qt.Unchecked def checkBoxDriver(self, item, column): if self.hasParent(item, column) == False: # zmenou u rodice se zmeni i vsechny deti myChildCount = item.childCount() for i in range (0, myChildCount): myChild = item.child(i) myChild.setCheckState (column, item.checkState(column)) def hasParent(self, item, column): try: parent = item.parent() parent.text(column) return True except: return False def rewriteConfig(self, item, column): parent = item.parent() itemText = str(item.text(column)) if self.hasParent(item, column) == True: # = nazev tabulky parentText = str(parent.text(column)) if item.checkState(column) == Qt.Checked: config['treeViewSet'][parentText][itemText] = 'True' if item.checkState(column) == Qt.Unchecked: config['treeViewSet'][parentText][itemText] = 'False' else: # = nazev atributu if item.checkState(column) == Qt.Checked: config['treeViewSet'][itemText + 'Root'] = 'True' if item.checkState(column) == Qt.PartiallyChecked: config['treeViewSet'][itemText + 'Root'] = 'Semi' if item.checkState(column) == Qt.Unchecked: config['treeViewSet'][itemText + 'Root'] = 'False' def nextId(self): if importRUIAN.databaseExists(): return LicenseWizard.PageImportParameters else: return LicenseWizard.PageCreateDBStructure