def on_analyses_viewmodel_updated(self, view_model): qmodel = QStandardItemModel() qmodel.itemChanged.connect(self.on_qmodel_itemChanged) qmodel.setColumnCount(5) qmodel.setHorizontalHeaderItem(0, QStandardItem('Ion')) qmodel.setHorizontalHeaderItem(1, QStandardItem('Method')) qmodel.setHorizontalHeaderItem(2, QStandardItem('Start')) qmodel.setHorizontalHeaderItem(3, QStandardItem('End')) qmodel.setHorizontalHeaderItem(4, QStandardItem('Reason')) root = qmodel.invisibleRootItem() for ion, analysis in view_model.analyses.items(): ion_name = QStandardItem(ion.name) ion_name.setData(ion, Qt.UserRole) method = QStandardItem(analysis.method) start = QStandardItem(str(round(analysis.range.start,2))) end = QStandardItem(str(round(analysis.range.end,2))) reason = QStandardItem(analysis.reason) root.appendRow([ion_name, method, start, end, reason]) self.rangedTable.setModel(qmodel) self.rangedTable.setItemDelegateForColumn(1, MethodsComboDelegate(view_model.methods, self.rangedTable)) for row in range(0, qmodel.rowCount()): self.rangedTable.openPersistentEditor(qmodel.index(row, 1)) self.rangedTable.setColumnWidth(1, 95) self.rangedTable.setContextMenuPolicy(3) self.rangedTable.customContextMenuRequested.connect(self._context_menu_requested) shortcut = QShortcut(QKeySequence('Del'), self.rangedTable, self._delete_ion,self._delete_ion, context=0)
def onConnectClick(self): # On remplit le champ Serveur s'il était vide if self.dlg.url.text() == "": self.dlg.url.setText("localhost") # On prépare la liste listView = self.dlg.layerList model = QStandardItemModel(listView) try: # On ouvre une connexion à la base self.connector = EsConnector(self.dlg.url.text(), self.dlg.port.text()) # On parcourt les index aliases = self.connector.makeGetCallToES("_aliases") for index in aliases: # On parcourt les types metadata = self.connector.makeGetCallToES(index) mappings = metadata[index]["mappings"] for type in mappings: # On parcourt les champs mapping = mappings[type]["properties"] for field in mapping: # Si le champ est de type geo_shape ou geo_point if mapping[field]["type"] == "geo_point" or mapping[ field]["type"] == "geo_shape": # On mémorise ce champ self.connector.addGeoField({ "index": index, "type": type, "field": field, "geotype": mapping[field]["type"] }) # On affiche ce champ dans la liste item = QStandardItem('- Index "' + index + '" / Type "' + type + '" / Champ "' + field + '" (' + mapping[field]["type"] + ')') model.appendRow(item) # Si au moins un champ a été trouvé if model.rowCount() > 0: # On met à jour le contenu de la liste listView.setModel(model) # On active le bouton "Ajouter" self.dlg.addLayers.setEnabled(True) else: self.iface.messageBar().pushMessage( "ElasticSearch Connector", 'Aucun champ "geo_shape" ou "geo_point" disponible', level=QgsMessageBar.WARNING, duration=5) # On se déconnecte de la base except ESConnectorException, e: self.iface.messageBar().pushMessage("ElasticSearch Connector", str(e), level=QgsMessageBar.CRITICAL, duration=5)
class DataModel(object): def __init__(self): super(DataModel,self).__init__() self.servers = QStandardItemModel(0,3) self.selected = '' self.autoconnect = False def loadSettings(self): settings = QSettings() servers = settings.value("servers", None) self.servers.clear() if servers: for s in servers: self.servers.appendRow([QStandardItem(str(i)) for i in s]) self.selected = str(settings.value("selected", self.selected)) self.autoconnect = int(settings.value("autoconnect", self.autoconnect)) def saveSettings(self): settings = QSettings() servers = [] if self.servers: for row in xrange(self.servers.rowCount()): entry = [] for col in xrange(self.servers.columnCount()): entry += [self.servers.item(row,col).text()] servers += [entry] if len(servers): settings.setValue("servers", servers) else: settings.setValue("servers", None) settings.setValue("selected", str(self.selected)) settings.setValue("autoconnect", int(self.autoconnect)) def selectedServer(self): selectedServer = [] if self.selected: result = self.servers.findItems( self.selected) if len(result): mi = result[0] row = mi.row() for col in xrange(self.servers.columnCount()): selectedServer += [self.servers.item(row,col).text()] return selectedServer
class NeoNavigationDock(QDockWidget, Ui_neoNavigationDock): """ Implements a navigation dock for Neo hierarchies. Tightly coupled with :class:`main_window_neo.MainWindowNeo`, the main reason for this class to exist is to keep the dock out of the general ui file. """ object_removed = pyqtSignal() # Signal to remove an object def __init__(self, parent): QDockWidget.__init__(self, parent) self.parent = parent self.setupUi(self) self.block_model = QStandardItemModel() self.segment_model = QStandardItemModel() self.channelgroup_model = QStandardItemModel() self.channel_model = QStandardItemModel() self.unit_model = QStandardItemModel() self.neoBlockList.setModel(self.block_model) self.neoSegmentList.setModel(self.segment_model) self.neoChannelGroupList.setModel(self.channelgroup_model) self.neoChannelList.setModel(self.channel_model) self.neoUnitList.setModel(self.unit_model) self.neoBlockList.doubleClicked.connect( lambda x: self._edit_item_annotations(x, self.block_model)) self.neoSegmentList.doubleClicked.connect( lambda x: self._edit_item_annotations(x, self.segment_model)) self.neoChannelGroupList.doubleClicked.connect( lambda x: self._edit_item_annotations(x, self.channelgroup_model)) self.neoChannelList.doubleClicked.connect( lambda x: self._edit_item_annotations(x, self.channel_model)) self.neoUnitList.doubleClicked.connect( lambda x: self._edit_item_annotations(x, self.unit_model)) self.neoBlockList.selectionModel().selectionChanged.connect( self.selected_blocks_changed) self.neoChannelGroupList.selectionModel().selectionChanged.connect( self.selected_channel_groups_changed) self.neoChannelList.selectionModel().selectionChanged.connect( self.selected_channels_changed) self.neoUnitList.selectionModel().selectionChanged.connect( self.selected_units_changed) self.neoSegmentList.selectionModel().selectionChanged.connect( self.selected_segments_changed) def clear(self): """ Clear all lists """ self.neoBlockList.clearSelection() self.block_model.clear() def get_letter_id(self, id_, small=False): """ Return a name consisting of letters given an integer """ if id_ < 0: return '' name = '' id_ += 1 if small: start = ord('a') else: start = ord('A') while id_ > 26: id_ -= 1 name += chr(start + (id_ % 26)) id_ /= 26 name += chr(start + id_ - 1) return name[::-1] def ensure_not_filtered(self, objects, all_objects, filters): """ Deactivates all filters that prevent the the given sequence of objects to be displayed. The passed filter tuple list is modified to only include valid filters. :param sequence objects: The objects that need to be visible. :param sequence all_objects: The whole object list to be filtered, including objects that are allowed to be hidden. :param sequence filters: A sequence of (Filter, name) tuples. """ objset = set(objects) if not objset.issubset( set(self.parent.filter_list(all_objects, filters))): i = 1 while i <= len(filters): test_filters = filters[:i] if objset.issubset(set(self.parent.filter_list( all_objects, test_filters))): i += 1 else: test_filters[-1][0].active = False filters.pop(i - 1) for o in objects: i = 0 while i < len(filters): if self.parent.is_filtered(o, [filters[i]]): filters[i][0].active = False filters.pop(i) else: i += 1 def filter_ordered(self, objects, filters): """ Filter a sequence of objects with a sequence of filters. Apply the filters in the order given by the sequence. Return the filtered list. """ for f in filters: if f[0].combined: objects = self.parent.filter_list(objects, [f]) else: objects = [o for o in objects if not self.parent.is_filtered(o, [f])] return objects def populate_neo_block_list(self): """ Fill the block list with appropriate entries. Qt.UserRole: The :class:`neo.Block` object """ self.block_model.clear() filters = self.parent.get_active_filters('Block') blocks = self.filter_ordered( self.parent.block_names.keys(), filters) for b in blocks: item = QStandardItem(self.parent.block_names[b]) item.setData(b, Qt.UserRole) self.block_model.appendRow(item) self.neoBlockList.setCurrentIndex(self.block_model.index(0, 0)) self.set_blocks_label() if not blocks: self.selected_blocks_changed() def populate_neo_segment_list(self): """ Fill the segment list with appropriate entries. Qt.UserRole: The :class:`neo.Segment` object """ self.segment_model.clear() segments = [] for b in self.blocks(): segments.extend(b.segments) filters = self.parent.get_active_filters('Segment') segments = self.filter_ordered(segments, filters) for i, s in enumerate(segments): if s.name: name = s.name + ' (%s-%i)' % \ (self.parent.block_ids[s.block], i) else: name = '%s-%i' % (self.parent.block_ids[s.block], i) new_item = QStandardItem(name) new_item.setData(s, Qt.UserRole) self.segment_model.appendRow(new_item) self.neoSegmentList.setCurrentIndex(self.segment_model.index(0, 0)) if api.config.autoselect_segments: self.neoSegmentList.selectAll() self.selected_segments_changed() def populate_neo_channel_group_list(self): """ Fill the channel group list with appropriate entries. Qt.UserRole: The :class:`neo.RecordingChannelGroup` object """ self.neoChannelGroupList.clearSelection() self.channelgroup_model.clear() self.parent.channel_group_names.clear() rcgs = [] for b in self.blocks(): rcgs.extend(b.recordingchannelgroups) filters = self.parent.get_active_filters( 'Recording Channel Group') rcgs = self.filter_ordered(rcgs, filters) for i, rcg in enumerate(rcgs): self.parent.channel_group_names[rcg] = '%s-%s' % ( self.parent.block_ids[rcg.block], self.get_letter_id(i, True)) if rcg.name: name = rcg.name + ' (%s)' % \ self.parent.channel_group_names[rcg] else: name = self.parent.channel_group_names[rcg] new_item = QStandardItem(name) new_item.setData(rcg, Qt.UserRole) self.channelgroup_model.appendRow(new_item) self.neoChannelGroupList.setCurrentIndex( self.channelgroup_model.index(0, 0)) if api.config.autoselect_channel_groups: self.neoChannelGroupList.selectAll() elif not rcgs: self.selected_channel_groups_changed() def populate_neo_channel_list(self): """ Fill the channel list with appropriate entries. Data slots: Qt.UserRole: The :class:`neo.RecordingChannel` Qt.UserRole+1: The channel index """ self.channel_model.clear() channels = set() rcs = [] rc_group_name = {} for rcg in self.recording_channel_groups(): for rc in rcg.recordingchannels: if not api.config.duplicate_channels and rc in channels: continue channels.add(rc) rcs.append(rc) rc_group_name[rc] = self.parent.channel_group_names[rcg] filters = self.parent.get_active_filters( 'Recording Channel') rcs = self.filter_ordered(rcs, filters) for rc in rcs: identifier = '%s.%d' % \ (rc_group_name[rc], rc.index) if rc.name: name = rc.name + ' (%s)' % identifier else: name = identifier new_item = QStandardItem(name) new_item.setData(rc, Qt.UserRole) new_item.setData(rc.index, Qt.UserRole + 1) self.channel_model.appendRow(new_item) if api.config.autoselect_channels: self.neoChannelList.selectAll() self.selected_channels_changed() def populate_neo_unit_list(self): """ Fill the unit list with appropriate entries. Qt.UserRole: The :class:`neo.Unit` object """ self.unit_model.clear() units = [] for rcg in self.recording_channel_groups(): units.extend(rcg.units) filters = self.parent.get_active_filters('Unit') units = self.filter_ordered(units, filters) for i, u in enumerate(units): if self.parent.is_filtered(u, filters): continue if u.name: name = u.name + ' (%s-%d)' % \ (self.parent.channel_group_names[rcg], i) else: name = '%s-%d' % (self.parent.channel_group_names[rcg], i) new_item = QStandardItem(name) new_item.setData(u, Qt.UserRole) self.unit_model.appendRow(new_item) if api.config.autoselect_units: self.neoUnitList.selectAll() self.selected_units_changed() def set_blocks_label(self): self.blocksLabel.setText( 'Blocks (%d/%d):' % (len(self.neoBlockList.selectedIndexes()), self.block_model.rowCount())) def set_channel_groups_label(self): self.channelGroupsLabel.setText( 'Channel Groups (%d/%d):' % ( len(self.neoChannelGroupList.selectedIndexes()), self.channelgroup_model.rowCount())) def selected_blocks_changed(self): self.set_blocks_label() self.populate_neo_channel_group_list() self.populate_neo_segment_list() def selected_channel_groups_changed(self): self.set_channel_groups_label() self.populate_neo_channel_list() self.populate_neo_unit_list() def selected_channels_changed(self): self.channelsLabel.setText( 'Channels (%d/%d):' % ( len(self.neoChannelList.selectedIndexes()), self.channel_model.rowCount())) def selected_units_changed(self): self.unitsLabel.setText( 'Units (%d/%d):' % ( len(self.neoUnitList.selectedIndexes()), self.unit_model.rowCount())) def selected_segments_changed(self): self.segmentsLabel.setText( 'Segments (%d/%d):' % ( len(self.neoSegmentList.selectedIndexes()), self.segment_model.rowCount())) def _edit_item_annotations(self, index, model): api.annotation_editor(model.data(index, Qt.UserRole)) def remove_selected(self, list_widget): """ Remove all selected objects from the given list widget. """ items = list_widget.selectedIndexes() if len(items) < 1: return model = list_widget.model() question = ('Do you really want to remove %d %s' % (len(items), type(model.data(items[0], Qt.UserRole)).__name__)) if len(items) > 1: question += 's' question += '?' if QMessageBox.question( self, 'Please confirm', question, QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: return for i in list_widget.selectedIndexes(): data = model.data(i, Qt.UserRole) if isinstance(data, neo.Block): self.parent.block_names.pop(data) else: spykeutils.tools.remove_from_hierarchy(data) list_widget.selectionModel().select(i, QItemSelectionModel.Deselect) self.object_removed.emit() def _context_actions(self, list_widget): idx = list_widget.currentIndex() if not idx: return [] data = list_widget.model().data(idx, Qt.UserRole) edit_action = QAction(get_icon('edit.png'), 'Edit annotations...', self) edit_action.triggered.connect( lambda x: self._edit_item_annotations(idx, list_widget.model())) delete_name = 'Delete %s' % type(data).__name__ if len(list_widget.selectedIndexes()) > 1: delete_name += 's' delete_action = QAction(get_icon('editdelete.png'), delete_name, self) delete_action.triggered.connect( lambda x: self.remove_selected(list_widget)) return [edit_action, delete_action] def on_neoBlockList_customContextMenuRequested(self, pos): if not self.neoBlockList.selectedIndexes(): return context_menu = QMenu(self) context_menu.addActions(self._context_actions(self.neoBlockList)) context_menu.popup(self.neoBlockList.mapToGlobal(pos)) def on_neoSegmentList_customContextMenuRequested(self, pos): if not self.neoSegmentList.selectedIndexes(): return context_menu = QMenu(self) context_menu.addActions(self._context_actions(self.neoSegmentList)) context_menu.popup(self.neoSegmentList.mapToGlobal(pos)) def on_neoChannelGroupList_customContextMenuRequested(self, pos): if not self.neoChannelGroupList.selectedIndexes(): return context_menu = QMenu(self) context_menu.addActions(self._context_actions(self.neoChannelGroupList)) context_menu.popup(self.neoChannelGroupList.mapToGlobal(pos)) def on_neoChannelList_customContextMenuRequested(self, pos): if not self.neoChannelList.selectedIndexes(): return context_menu = QMenu(self) context_menu.addActions(self._context_actions(self.neoChannelList)) context_menu.popup(self.neoChannelList.mapToGlobal(pos)) def on_neoUnitList_customContextMenuRequested(self, pos): if not self.neoUnitList.selectedIndexes(): return context_menu = QMenu(self) context_menu.addActions(self._context_actions(self.neoUnitList)) context_menu.popup(self.neoUnitList.mapToGlobal(pos)) def blocks(self): """ Return selected :class:`neo.Block` objects. """ return [self.block_model.data(i, Qt.UserRole) for i in self.neoBlockList.selectedIndexes()] def segments(self): """ Return selected :class:`neo.Segment` objects. """ return [self.segment_model.data(i, Qt.UserRole) for i in self.neoSegmentList.selectedIndexes()] def recording_channel_groups(self): """ Return selected :class:`neo.RecordingChannelGroup` objects. """ return [self.channelgroup_model.data(i, Qt.UserRole) for i in self.neoChannelGroupList.selectedIndexes()] def recording_channels(self): """ Return selected :class:`neo.RecordingChannel` objects. """ return [self.channel_model.data(i, Qt.UserRole) for i in self.neoChannelList.selectedIndexes()] def units(self): """ Return selected :class:`neo.Unit` objects. """ return [self.unit_model.data(i, Qt.UserRole) for i in self.neoUnitList.selectedIndexes()] def set_selection(self, data): """ Set the selected data. """ block_list = [] for b in data['blocks']: cl = None rp = None if len(b) > 2: cl = NeoDataProvider.find_io_class(b[2]) if len(b) > 3: rp = b[3] loaded = NeoDataProvider.get_block( b[1], b[0], force_io=cl, read_params=rp) if loaded is None: raise IOError('One of the files contained in the ' 'selection could not be loaded!') block_list.append(loaded) block_set = set([(b[0], b[1]) for b in data['blocks']]) # Select blocks self.ensure_not_filtered(block_list, self.parent.block_names.keys(), self.parent.get_active_filters('Block')) self.populate_neo_block_list() selection = QItemSelection() for i in self.block_model.findItems( '*', Qt.MatchWrap | Qt.MatchWildcard): block = i.data(Qt.UserRole) t = (NeoDataProvider.block_indices[block], self.parent.block_files[block]) if t in block_set: selection.append(QItemSelectionRange( self.block_model.indexFromItem(i))) self.neoBlockList.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) # Select segments seg_list = [block_list[idx[1]].segments[idx[0]] for idx in data['segments']] all_segs = [] for b in self.blocks(): all_segs.extend(b.segments) self.ensure_not_filtered(seg_list, all_segs, self.parent.get_active_filters('Segment')) self.populate_neo_segment_list() selection = QItemSelection() for i in self.segment_model.findItems( '*', Qt.MatchWrap | Qt.MatchWildcard): segment = i.data(Qt.UserRole) if not segment.block in block_list: continue seg_idx = segment.block.segments.index(segment) block_idx = block_list.index(segment.block) if [seg_idx, block_idx] in data['segments']: selection.append(QItemSelectionRange( self.segment_model.indexFromItem(i))) self.neoSegmentList.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) # Select recording channel groups rcg_list = [block_list[rcg[1]].recordingchannelgroups[rcg[0]] for rcg in data['channel_groups']] all_rcgs = [] for b in self.blocks(): all_rcgs.extend(b.recordingchannelgroups) self.ensure_not_filtered( rcg_list, all_rcgs, self.parent.get_active_filters('Recording Channel Group')) self.populate_neo_channel_group_list() selection = QItemSelection() for i in self.channelgroup_model.findItems( '*', Qt.MatchWrap | Qt.MatchWildcard): rcg = i.data(Qt.UserRole) if not rcg.block in block_list: continue rcg_idx = rcg.block.recordingchannelgroups.index(rcg) block_idx = block_list.index(rcg.block) if [rcg_idx, block_idx] in data['channel_groups']: selection.append(QItemSelectionRange( self.channelgroup_model.indexFromItem(i))) self.neoChannelGroupList.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) # Select channels rc_list = [rcg_list[rc[1]].recordingchannels[rc[0]] for rc in data['channels']] all_rcs = [] for rcg in self.recording_channel_groups(): for rc in rcg.recordingchannels: if not api.config.duplicate_channels and rc in all_rcs: continue all_rcs.append(rc) self.ensure_not_filtered( rc_list, all_rcs, self.parent.get_active_filters('Recording Channel')) self.populate_neo_channel_list() selection = QItemSelection() rcg_set = set(rcg_list) for i in self.channel_model.findItems( '*', Qt.MatchWrap | Qt.MatchWildcard): channel = i.data(Qt.UserRole) if not set(channel.recordingchannelgroups).intersection(rcg_set): continue for rcg in channel.recordingchannelgroups: if [rcg.recordingchannels.index(channel), rcg_list.index(rcg)] in data['channels']: selection.append(QItemSelectionRange( self.channel_model.indexFromItem(i))) break self.neoChannelList.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) # Select units unit_list = [rcg_list[u[1]].units[u[0]] for u in data['units']] all_units = [] for rcg in self.recording_channel_groups(): all_units.extend(rcg.units) self.ensure_not_filtered( unit_list, all_units, self.parent.get_active_filters('Unit')) self.populate_neo_unit_list() selection = QItemSelection() for i in self.unit_model.findItems( '*', Qt.MatchWrap | Qt.MatchWildcard): unit = i.data(Qt.UserRole) if unit.recordingchannelgroup not in rcg_list: continue rcg_idx = rcg_list.index(unit.recordingchannelgroup) unit_idx = unit.recordingchannelgroup.units.index(unit) if [unit_idx, rcg_idx] in data['units']: selection.append(QItemSelectionRange( self.unit_model.indexFromItem(i))) self.neoUnitList.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) self.parent.refresh_filters()
class ListPairTableView(QTableView): """ 2-column table view that enables pairing of list data through combo boxes. """ def __init__(self, parent=None): QTableView.__init__(self, parent) self.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.SelectedClicked) self.setSelectionBehavior(QAbstractItemView.SelectRows) self._pair_model = QStandardItemModel(1, 2, self) self._pair_model.dataChanged.connect(self._on_pair_data_changed) self.setModel(self._pair_model) self.horizontalHeader().setResizeMode(QHeaderView.Stretch) self._combo_delegate = PairComboBoxDelegate(self) self.setItemDelegate(self._combo_delegate) def set_header_labels(self, labels): """ Set the table's header labels using labels. :param labels: Header labels. :type labels: list """ if len(labels) < 2: return lbls = [] for i in range(2): lbls.append(labels[i]) self._pair_model.setHorizontalHeaderLabels(lbls) def clear_view(self): """ Clears all row pairings in the view. """ rows = self._pair_model.rowCount() self._pair_model.removeRows(0, rows) # Insert blank row self.append_row() def append_row(self): """ Add a blank row after the last item in the view. """ items = [QStandardItem(), QStandardItem()] self._pair_model.appendRow(items) def set_combo_selection(self, selection, empty_item=True): """ Set combo selection for both columns. Any existing rows will be removed from the view. :param selection: A list containing two sub-lists for each column that correspond to the selection list for the combobox in each column. :type selection: list :param empty_item: True to insert an empty first item in each of the column comboboxes. :type empty_item: bool """ self._combo_delegate.set_items_pair(selection, empty_item) self.clear_view() def _on_pair_data_changed(self, old_index, new_index): """ This slot asserts whether selections in both columns in a row have been specified. If true, then automatically adds a new empty row for additional entries; If false, then the empty is removed from the view. :param old_index: Model index :type old_index: QModelIndex :param new_index: Model index :type new_index: QModelIndex """ row_state = self.row_data_state(new_index.row()) row_data = self.row_data(new_index.row()) if row_state == 0: self._pair_model.removeRows(new_index.row(), 1) if self._pair_model.rowCount() == 0: self.append_row() elif row_state == 2: if not self.is_last_row_empty(): self.append_row() def is_last_row_empty(self): """ :return: True if the last row in the view does not contain any data, False if one or both columns contains data. :rtype: bool """ last_row_idx = self._pair_model.rowCount() - 1 last_row_state = self.row_data_state(last_row_idx) if last_row_state == 0: return True else: return False def row_data_state(self, row_index): """ :param row_index: Row position :type row_index: int :return: 0 if data for each of the columns is empty. 1 if one column contains data and the other is empty. 2 if both columns contain data. :rtype: int """ col_0_val, col_1_val = self.row_data(row_index) if col_0_val is None and col_1_val is None: return 0 elif self._is_empty(col_0_val) and not self._is_empty(col_1_val): return 1 elif not self._is_empty(col_0_val) and self._is_empty(col_1_val): return 1 elif self._is_empty(col_0_val) and self._is_empty(col_1_val): return 0 elif not self._is_empty(col_0_val) and not self._is_empty(col_1_val): return 2 def _is_empty(self, val): if val is None: return True else: if (isinstance(val, str) or isinstance(val, unicode)) and not val: return True return False def row_data(self, row_index): """ :param row_index: Row position :type row_index: int :return: Data in both first and second columns for the specified row. :rtype: tuple """ if row_index >= 0: idx_col_0 = self._pair_model.index(row_index, 0) idx_col_1 = self._pair_model.index(row_index, 1) val_0 = self._pair_model.data(idx_col_0) val_1 = self._pair_model.data(idx_col_1) return val_0, val_1 else: return None, None def column_pairings(self): """ :return: Collection of column matchings specified as specified by the user. :rtype: dict """ col_pairings = {} for row_idx in range(self._pair_model.rowCount()): if self.row_data_state(row_idx) != 0: col_val_0, col_val_1 = self.row_data(row_idx) col_pairings[col_val_0] = col_val_1 return col_pairings
class SubPowerWidget(QWidget): """ @brief Zeigt alle Unterkräfte in einer Baumstruktur an. """ def __init__(self, template, character, parent=None): super(SubPowerWidget, self).__init__(parent) self.__storage = template self.__character = character self.__model = QStandardItemModel() # Das ungenutzte Model dient dazu, alle Unterkräfte aufzunehmen, die ich nicht darstellen möchte. Ist einfacher, als diese im View zu verstecken. self.__modelUnused = QStandardItemModel() self._layout = QVBoxLayout() self.setLayout( self._layout ) self.__view = QTreeView() self.__view.setHeaderHidden(True) self.__view.setModel( self.__model) self._layout.addWidget(self.__view) self._typ = "Subpower" categories = self.__storage.categories(self._typ) self.__items = {} self.__rootItem = QStandardItem() self.__rootItem = self.__model.invisibleRootItem() self.__rootItemUnused = QStandardItem() self.__rootItemUnused = self.__modelUnused.invisibleRootItem() for item in categories: categoryItem = QStandardItem(item) self.__rootItem.appendRow(categoryItem) ## Ich benötige diese Items auch im ungenutzten Model. categoryItemUnused = QStandardItem(item) self.__rootItemUnused.appendRow(categoryItemUnused) traitList = list( self.__character.traits[self._typ][item].items() ) traitList.sort() for trait in traitList: traitItem = QStandardItem(trait[1].name) traitItem.setCheckable(True) ## Unhashable Type self.__items[trait[1]] = traitItem categoryItem.appendRow(traitItem) ## Funktioniert mit PySide nicht: #trait[1].availableChanged.connect(traitItem.setEnabled) ## Funktioniert auch mit PySide: trait[1].availableChanged.connect( lambda enable, item=traitItem: item.setEnabled(enable) ) trait[1].valueChanged.connect( lambda val, trait=trait[1], item=traitItem: self.__setItemValue(trait, item) ) self.__model.itemChanged.connect(self.__getItemValue) self.__character.speciesChanged.connect(self.hideOrShowToolPage) self.__character.breedChanged.connect(self.hideOrShowToolPage) self.__character.factionChanged.connect(self.hideOrShowToolPage) def __setItemValue(self, trait, item): """ Setzt den Wert der Angezeigten Items. """ if trait.value == 0: item.setCheckState(Qt.Unchecked) elif trait.value == 1: item.setCheckState(Qt.PartiallyChecked) else: item.setCheckState(Qt.Checked) def __getItemValue(self, item): """ Setzt den Wert der Eigenschaft im Speicher. """ for trait in self.__items.items(): if id(trait[1]) == id(item): trait[0].value = item.checkState() break def hideOrShowToolPage(self, res): """ Alle Eigenschaften, die nicht zur Verfügung stehen, werden verborgen, indem sie in ein anderes Model verschoben werden. \bug Möglicher Fehler in PySide: Der Aufruf von QStandardItem.model() führt beim Beenden des Programms zu einem Segmentation Fault. """ # Versteckt alle Unterkräfte, die zu gewähltem Charakter nicht passen. for item in self.__items.items(): if ( ( item[0].species and item[0].species != self.__character.species ) or ( item[0].only and self.__character.breed not in item[0].only and self.__character.faction not in item[0].only ) ): #self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), True) #Debug.debug(item[1].model()) ## Hier wird beispielsweise besagter Aufruf getätigt, der zu einem segfault führt. if item[1].model() == self.__model: parent = item[1].parent() itemUnused = parent.takeRow(item[1].index().row()) parentUnused = self.__modelUnused.findItems(parent.text())[0] parentUnused.appendRow(itemUnused) else: #self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), False) if item[1].model() == self.__modelUnused: parent = item[1].parent() itemUsed = parent.takeRow(item[1].index().row()) parentUsed = self.__model.findItems(parent.text())[0] parentUsed.appendRow(itemUsed) ## Versteckt alle Elternzeilen, wenn sie keine Kinder enthalten. for i in range(self.__model.rowCount()): categoryItem = self.__model.item(i) if categoryItem.hasChildren(): self.__view.setRowHidden(categoryItem.index().row(), self.__rootItem.index(), False) else: self.__view.setRowHidden(categoryItem.index().row(), self.__rootItem.index(), True)
class TreeView(QTreeView): def __init__(self, parent): QTreeView.__init__(self, parent) while not isinstance(parent, QDialog) and not isinstance(parent, QMainWindow): parent = parent.parent() self.setObjectName("TreeView" + str(len(parent.findChildren(TreeView)))) # self.setObjectName("TreeViewWidget") # self.hLayout = QHBoxLayout(self) # self.hLayout.setObjectName("hLayout") # # sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) # sizePolicy.setHorizontalStretch(0) # sizePolicy.setVerticalStretch(0) # sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) # self.setSizePolicy(sizePolicy) # # # self.frame = Frame() # self = QTreeView(self) # self.hLayout.addWidget(self) self.stdModel = QStandardItemModel() self.setModel(self.stdModel) self.hasObject = False self.treeNodeList = [] self.checkBoxList = [] self.setHeaderHidden(True) # self.stdModel.appendRow(TreeNode("P")) # rootIndex = self.rootIndex() # rootItem = self.stdModel.itemFromIndex(rootIndex) # rootItem.setText("Root") def mouseMoveEvent(self, mouseEvent): pt = mouseEvent.pos() pass def Clear(self): self.stdModel.clear() self.hasObject = False self.treeNodeList = [] def Add(self, caption): item = TreeNode(caption) if len(self.treeNodeList) > 0: item.PrevNode = self.treeNodeList[len(self.treeNodeList) - 1] item.PrevNode.NextNode = item item.Index = len(self.treeNodeList) # item.nodeIndex = len(self.treeNodeList) self.treeNodeList.append(item) self.stdModel.appendRow(item) return item def RemoveNode(self, i): self.stdModel.removeRow(i) self.treeNodeList.pop(i) for j in range(i, len(self.treeNodeList)): self.treeNodeList[j].nodeIndex -= 1 def Remove(self, item): removedIndex = self.treeNodeList.index(item) if removedIndex == 0: self.treeNodeList[1].PrevNode = None elif removedIndex == len(self.treeNodeList) - 1: self.treeNodeList[len(self.treeNodeList) - 2].NextNode = None else: self.treeNodeList[removedIndex + 1].PrevNode = self.treeNodeList[removedIndex - 1] self.treeNodeList[removedIndex - 1].NextNode = self.treeNodeList[removedIndex + 1] self.treeNodeList.pop(removedIndex) self.stdModel.removeRow(removedIndex) i = 0 for node in self.treeNodeList: node.Index = i node.LastNode = self.treeNodeList[len(self.treeNodeList) - 1] i += 1 def Insert(self, index, text): if index == 0 and len(self.treeNodeList) == 0: self.Add(text) return node = TreeNode(text) node.Parent = self self.treeNodeList.insert(index, node) i = 0 for node0 in self.treeNodeList: node0.Index = i i += 1 if index == 0: self.treeNodeList[index].PrevNode = None if len(self.treeNodeList) == 1: self.treeNodeList[index].NextNode = None self.treeNodeList[index].LastNode = self.treeNodeList[index] else: self.treeNodeList[index].NextNode = self.treeNodeList[index + 1] self.treeNodeList[index].LastNode = self.treeNodeList[len(self.treeNodeList) - 1] self.treeNodeList[index + 1].PrevNode = self.treeNodeList[index] else: self.treeNodeList[index].PrevNode = self.treeNodeList[index - 1] self.treeNodeList[index].NextNode = self.treeNodeList[index + 1] self.treeNodeList[index].LastNode = self.treeNodeList[len(self.treeNodeList) - 1] self.treeNodeList[index + 1].PrevNode = self.treeNodeList[index] self.treeNodeList[index - 1].NextNode = self.treeNodeList[index] self.stdModel.insertRow(index, node) return node def get_Items(self): return self.treeNodeList Nodes = property(get_Items, None, None, None) def Node(self, index): if not self.stdModel.rowCount() > 0: return None return self.treeNodeList[index] def getSelectedNode(self): if not self.stdModel.rowCount() > 0: return None index = self.currentIndex() return self.stdModel.itemFromIndex(index) def setSelectedNode(self, node): if not self.stdModel.rowCount() > 0: return # self.s index = self.stdModel.indexFromItem(node) self.setCurrentIndex(index) # self.treeNodeList.pop(index) # self.treeNodeList.insert(index, node) # self.stdModel.setItem(index, node) SelectedNode = property(getSelectedNode, setSelectedNode, None, None) def get_Enabled(self): return self.isEnabled() def set_Enabled(self, bool): self.setEnabled(bool) Enabled = property(get_Enabled, set_Enabled, None, None) def get_Visible(self): return self.isVisible() def set_Visible(self, bool): self.setVisible(bool) Visible = property(get_Visible, set_Visible, None, None)
class TemporalSpectralProfilePlugin: POINT_SELECTION = 0 SELECTED_POLYGON = 1 def __init__(self, iface): self.iface = iface self.canvas = iface.mapCanvas() self.wdg = None self.pointTool = None def initGui(self): # create action self.action = QAction(QIcon(":/plugins/temporalprofiletool/icons/temporalProfileIcon.png"), "Temporal/Spectral Profile", self.iface.mainWindow()) self.action.setWhatsThis("Plots temporal/spectral profiles") QObject.connect(self.action, SIGNAL("triggered()"), self.run) self.aboutAction = QAction("About", self.iface.mainWindow()) QObject.connect(self.aboutAction, SIGNAL("triggered()"), self.about) # add toolbar button and menu item self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu("&Profile Tool", self.action) self.iface.addPluginToMenu("&Profile Tool", self.aboutAction) #Init class variables self.pointTool = ProfiletoolMapTool(self.iface.mapCanvas(),self.action) #the mouselistener self.dockOpened = False #remember for not reopening dock if there's already one opened self.pointstoDraw = None #Polyline in mapcanvas CRS analysed self.dblclktemp = None #enable disctinction between leftclick and doubleclick self.mdl = None #the model whitch in are saved layers analysed caracteristics self.selectionmethod = 0 #The selection method defined in option self.saveTool = self.canvas.mapTool() #Save the standard mapttool for restoring it at the end self.plotlibrary = None #The plotting library to use self.pointSelectionInstructions = "Click on a raster for temporal/spectral profile (right click to cancel then quit)" self.selectedPolygonInstructions = 'Use "Select Features" tool to select polygon(s) designating AOI for which temporal/spectral profile should be calculated' def unload(self): if not self.wdg is None: self.wdg.close() self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu("&Profile Tool", self.action) self.iface.removePluginMenu("&Profile Tool", self.aboutAction) def run(self): # first, check posibility if self.checkIfOpening() == False: return #if dock not already opened, open the dock and all the necessary thing (model,doProfile...) if self.dockOpened == False: self.mdl = QStandardItemModel(0, 6) self.wdg = PTDockWidget(self.iface.mainWindow(), self.iface, self.mdl) self.wdg.showIt() self.doprofile = DoProfile(self.iface,self.wdg,self.pointTool, self) self.tableViewTool = TableViewTool() QObject.connect(self.wdg, SIGNAL( "closed(PyQt_PyObject)" ), self.cleaning2) QObject.connect(self.wdg.tableView,SIGNAL("clicked(QModelIndex)"), self._onClick) QObject.connect(self.wdg.pushButton_2, SIGNAL("clicked()"), self.addLayer) QObject.connect(self.wdg.pushButton, SIGNAL("clicked()"), self.removeLayer) QObject.connect(self.wdg.comboBox, SIGNAL("currentIndexChanged(int)"), self.selectionMethod) QObject.connect(self.wdg.cboLibrary, SIGNAL("currentIndexChanged(int)"), self.changePlotLibrary) QObject.connect(self.wdg.cboXAxis, SIGNAL("currentIndexChanged(int)"), self.changeXAxisLabeling) QObject.connect(self.wdg.leXAxisSteps, SIGNAL("editingFinished()"), self.changeXAxisLabeling) QObject.connect(self.wdg.dateTimeEditCurrentTime, SIGNAL("editingFinished()"), self.changeXAxisLabeling) QObject.connect(self.wdg.spinBoxTimeExtent, SIGNAL("editingFinished()"), self.changeXAxisLabeling) QObject.connect(self.wdg.cboTimeExtent, SIGNAL("currentIndexChanged(int)"), self.changeXAxisLabeling) QObject.connect(self.wdg.cbTimeDimension, SIGNAL("stateChanged(int)"), self.changeXAxisLabeling) self.wdg.addOptionComboboxItems() self.addLayer() self.dockOpened = True #Listeners of mouse self.connectPointMapTool() #init the mouse listener comportement and save the classic to restore it on quit self.canvas.setMapTool(self.pointTool) #Help about what doing if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.iface.mainWindow().statusBar().showMessage(self.pointSelectionInstructions ) elif self.selectionmethod == TemporalSpectralProfilePlugin.SELECTED_POLYGON: self.iface.mainWindow().statusBar().showMessage(self.selectedPolygonInstructions) QObject.connect(QgsMapLayerRegistry.instance(), SIGNAL("layersWillBeRemoved (QStringList)"), self.onLayersWillBeRemoved) #************************************* Canvas listener actions ********************************************** # Used when layer is about to be removed from QGIS Map Layer Registry def onLayersWillBeRemoved(self, layersIds): if self.mdl is not None: for layerId in layersIds: for row in range(self.mdl.rowCount()): if layerId == self.mdl.index(row, 3).data().id(): self.removeLayer(row) self.onLayersWillBeRemoved(layersIds) break # Use for selected polygon option def selectionChanged(self, layer): if not layer.geometryType() == QGis.Polygon: return fullGeometry = QgsGeometry() for feature in layer.selectedFeatures(): if fullGeometry.isEmpty(): fullGeometry = QgsGeometry(feature.constGeometry()) else: fullGeometry = fullGeometry.combine(feature.constGeometry()) if not fullGeometry.isEmpty(): crs = osr.SpatialReference() crs.ImportFromProj4(str(layer.crs().toProj4())) self.doprofile.calculatePolygonProfile(fullGeometry, crs, self.mdl, self.plotlibrary) #************************************* Mouse listener actions *********************************************** # Used for point selection option def moved(self, point): if self.wdg and not self.wdg.cbPlotWhenClick.isChecked(): if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.doubleClicked(point) if self.selectionmethod == TemporalSpectralProfilePlugin.SELECTED_POLYGON: pass def rightClicked(self, point): #used to quit the current action self.cleaning() def leftClicked(self, point): self.doubleClicked(point) def doubleClicked(self, point): if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.iface.mainWindow().statusBar().showMessage(str(point.x())+", "+str(point.y())) self.doprofile.calculatePointProfile(point, self.mdl, self.plotlibrary) if self.selectionmethod == TemporalSpectralProfilePlugin.SELECTED_POLYGON: return #***************************** open and quit options ******************************************* def checkIfOpening(self): if self.iface.mapCanvas().layerCount() == 0: #Check a layer is opened QMessageBox.warning(self.iface.mainWindow(), "Profile", "First open a raster layer, please") return False layer = self.iface.activeLayer() if layer == None or not isProfilable(layer) : #Check if a raster layer is opened and selected if self.mdl == None or self.mdl.rowCount() == 0: QMessageBox.warning(self.iface.mainWindow(), "Profile Tool", "Please select a raster layer") return False return True def connectPointMapTool(self): QObject.connect(self.pointTool, SIGNAL("moved"), self.moved) QObject.connect(self.pointTool, SIGNAL("rightClicked"), self.rightClicked) QObject.connect(self.pointTool, SIGNAL("leftClicked"), self.leftClicked) QObject.connect(self.pointTool, SIGNAL("doubleClicked"), self.doubleClicked) QObject.connect(self.pointTool, SIGNAL("deactivate"), self.deactivatePointMapTool) def deactivatePointMapTool(self): #enable clean exit of the plugin QObject.disconnect(self.pointTool, SIGNAL("moved"), self.moved) QObject.disconnect(self.pointTool, SIGNAL("leftClicked"), self.leftClicked) QObject.disconnect(self.pointTool, SIGNAL("rightClicked"), self.rightClicked) QObject.disconnect(self.pointTool, SIGNAL("doubleClicked"), self.doubleClicked) self.iface.mainWindow().statusBar().showMessage("") def connectSelectedPolygonsTool(self): QObject.connect(self.iface.mapCanvas(), SIGNAL("selectionChanged(QgsMapLayer *)"), self.selectionChanged) def deactivateSelectedPolygonsTools(self): QObject.disconnect(self.iface.mapCanvas(), SIGNAL("selectionChanged(QgsMapLayer *)"), self.selectionChanged) def cleaning(self): #used on right click self.canvas.unsetMapTool(self.pointTool) self.canvas.setMapTool(self.saveTool) self.iface.mainWindow().statusBar().showMessage("") def cleaning2(self): #used when Dock dialog is closed QObject.disconnect(self.wdg.tableView,SIGNAL("clicked(QModelIndex)"), self._onClick) if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.deactivatePointMapTool() else: self.deactivateSelectedPolygonsTools() self.selectionmethod = TemporalSpectralProfilePlugin.POINT_SELECTION QObject.disconnect(self.wdg.comboBox, SIGNAL("currentIndexChanged(int)"), self.selectionMethod) QObject.disconnect(QgsMapLayerRegistry.instance(), SIGNAL("layersWillBeRemoved (QStringList)"), self.onLayersWillBeRemoved) self.mdl = None self.dockOpened = False self.cleaning() self.wdg = None #***************************** Options ******************************************* def selectionMethod(self,item): if item == TemporalSpectralProfilePlugin.POINT_SELECTION: self.selectionmethod = TemporalSpectralProfilePlugin.POINT_SELECTION self.pointTool.setCursor(Qt.CrossCursor) self.deactivateSelectedPolygonsTools() self.connectPointMapTool() if not self.canvas.mapTool() == self.pointTool: self.canvas.setMapTool(self.pointTool) self.iface.mainWindow().statusBar().showMessage(self.pointSelectionInstructions) self.wdg.changeStatComboBoxItems(self.doprofile.getPointProfileStatNames()) elif item == TemporalSpectralProfilePlugin.SELECTED_POLYGON: self.selectionmethod = TemporalSpectralProfilePlugin.SELECTED_POLYGON self.deactivatePointMapTool() self.connectSelectedPolygonsTool() self.iface.actionSelectRectangle().trigger() self.iface.mainWindow().statusBar().showMessage(self.selectedPolygonInstructions) self.wdg.changeStatComboBoxItems(self.doprofile.getPolygonProfileStatNames(), "mean") def changePlotLibrary(self, item): self.plotlibrary = self.wdg.cboLibrary.itemText(item) self.wdg.addPlotWidget(self.plotlibrary) self.changeXAxisLabeling() def changeXAxisLabeling(self): self.xAxisSteps = {} # default band number labeling if self.wdg.cboXAxis.currentIndex() == 0: self.doprofile.xAxisSteps = None # Labels from string elif self.wdg.cboXAxis.currentIndex() == 1: self.doprofile.xAxisSteps = self.wdg.leXAxisSteps.text().split(';') try: self.doprofile.xAxisSteps = [ float(x) for x in self.doprofile.xAxisSteps ] except ValueError: self.doprofile.xAxisSteps = None text = "Temporal/Spectral Profile Tool: The X-axis steps' string " + \ "is invalid. Using band numbers instead." self.iface.messageBar().pushWidget(self.iface.messageBar().createMessage(text), QgsMessageBar.WARNING, 5) # Labels based on time elif self.wdg.cboXAxis.currentIndex() == 2: self.doprofile.xAxisSteps = ["Timesteps", self.wdg.dateTimeEditCurrentTime.dateTime().toPyDateTime(), int(self.wdg.spinBoxTimeExtent.cleanText()), self.wdg.cboTimeExtent.currentText(), self.wdg.cbTimeDimension.isChecked()] if self.plotlibrary == "Qwt5": text = "Temporal/Spectral Profile Tool: There is currently no support using " + \ "Time steps while using the Qwt plotlibrary" self.iface.messageBar().pushWidget(self.iface.messageBar().createMessage(text), QgsMessageBar.WARNING, 5) self.doprofile.xAxisSteps = None #************************* tableview function ****************************************** def addLayer(self): layer = self.iface.activeLayer() if isProfilable(layer): self.tableViewTool.addLayer(self.iface, self.mdl, layer) def _onClick(self,index1): #action when clicking the tableview self.tableViewTool.onClick(self.iface, self.wdg, self.mdl, self.plotlibrary, index1) def removeLayer(self, index = None): if index is None: index = self.tableViewTool.chooseLayerForRemoval(self.iface, self.mdl) if index is not None: self.tableViewTool.removeLayer(self.mdl, index) PlottingTool().clearData(self.wdg, self.mdl, self.plotlibrary) def about(self): from ui.dlgabout import DlgAbout DlgAbout(self.iface.mainWindow()).exec_()
class AbstractStoreWidget(QWidget): """ @brief Ein einfaches Widget, um das Inventar des Charakters zu füllen. """ itemBought = Signal(str, str) itemSold = Signal(str, str) def __init__(self, template, character, parent=None): super(AbstractStoreWidget, self).__init__(parent) self.ui = Ui_AbstractStoreWidget() self.ui.setupUi(self) self.__character = character self.__storage = template self.__modelInventory = QStandardItemModel() self.ui.view_inventory.setModel(self.__modelInventory) self.__modelStore = QStandardItemModel() self.ui.view_store.setModel(self.__modelStore) ## Resources self.ui.traitDots_resources.valueChanged.connect( self.__character.traits["Merit"]["Social"]["Resources"].setValue) self.__character.traits["Merit"]["Social"][ "Resources"].valueChanged.connect( self.ui.traitDots_resources.setValue) self.ui.traitDots_enhancedItem.valueChanged.connect( self.__character.traits["Merit"]["Item"]["Enhanced Item"].setValue) self.__character.traits["Merit"]["Item"][ "Enhanced Item"].valueChanged.connect( self.ui.traitDots_enhancedItem.setValue) ## Items self.ui.traitDots_token.maximum = 10 self.ui.traitDots_imbuedItem.maximum = 10 self.ui.traitDots_artifact.maximum = 10 self.ui.traitDots_cursedItem.valueChanged.connect( self.__character.traits["Merit"]["Item"]["Cursed Item"].setValue) self.ui.traitDots_fetish.valueChanged.connect( self.__character.traits["Merit"]["Item"]["Fetish"].setValue) self.ui.traitDots_token.valueChanged.connect( self.__character.traits["Merit"]["Item"]["Token"].setValue) self.ui.traitDots_imbuedItem.valueChanged.connect( self.__character.traits["Merit"]["Item"]["Imbued Item"].setValue) self.ui.traitDots_artifact.valueChanged.connect( self.__character.traits["Merit"]["Item"]["Artifact"].setValue) self.__character.traits["Merit"]["Item"][ "Cursed Item"].valueChanged.connect( self.ui.traitDots_cursedItem.setValue) self.__character.traits["Merit"]["Item"][ "Fetish"].valueChanged.connect(self.ui.traitDots_fetish.setValue) self.__character.traits["Merit"]["Item"]["Token"].valueChanged.connect( self.ui.traitDots_token.setValue) self.__character.traits["Merit"]["Item"][ "Imbued Item"].valueChanged.connect( self.ui.traitDots_imbuedItem.setValue) self.__character.traits["Merit"]["Item"][ "Artifact"].valueChanged.connect( self.ui.traitDots_artifact.setValue) self.ui.pushButton_add.setIcon( QIcon(":/icons/images/actions/1leftarrow.png")) self.ui.pushButton_remove.setIcon( QIcon(":/icons/images/actions/1rightarrow.png")) self.__modelInventory.rowsInserted.connect(self.checkButtonState) self.__modelInventory.rowsRemoved.connect(self.checkButtonState) self.__modelStore.rowsInserted.connect(self.checkButtonState) self.__modelStore.rowsRemoved.connect(self.checkButtonState) self.ui.pushButton_add.clicked.connect(self.buyItem) self.ui.view_store.doubleClicked.connect(self.buyItem) self.ui.pushButton_remove.clicked.connect(self.sellItem) self.ui.view_inventory.doubleClicked.connect(self.sellItem) self.ui.lineEdit_custom.textChanged.connect( self.changeCustomButtonState) self.ui.pushButton_addCustom.clicked.connect(self.buyCustomItem) def setEnhancedItemTraitsVisible(self, sw=True): self.ui.label_enhancedItem.setVisible(sw) self.ui.traitDots_enhancedItem.setVisible(sw) def setMagicalItemTraitsVisible(self, sw=True): self.ui.label_cursedItem.setVisible(sw) self.ui.traitDots_cursedItem.setVisible(sw) self.ui.label_fetish.setVisible(sw) self.ui.traitDots_fetish.setVisible(sw) self.ui.label_token.setVisible(sw) self.ui.traitDots_token.setVisible(sw) self.ui.label_artifact.setVisible(sw) self.ui.traitDots_artifact.setVisible(sw) self.ui.label_imbuedItem.setVisible(sw) self.ui.traitDots_imbuedItem.setVisible(sw) def setAddCustomVisible(self, sw=True): self.ui.widget_custom.setVisible(sw) def addItemToStore(self, name, category=None, icon=None): newItem = QStandardItem(name) if icon: newItem.setIcon(icon) if category: newItem.setData(category) self.__modelStore.appendRow(newItem) def buyItem(self): """ Der besagte Gegenstand wird vom Laden in das Inventar übernommen. """ listOfItems = self.__modelStore.takeRow( self.ui.view_store.currentIndex().row()) self.__modelInventory.appendRow(listOfItems) self.itemBought.emit(listOfItems[0].text(), listOfItems[0].data()) def __customItem(self, name): """ Erzeugt einen vom Benutzer benannten Gegenstand. """ if name: existingItemInventory = self.__modelInventory.findItems(name) if not existingItemInventory: existingItem = self.__modelStore.findItems(name) if existingItem: listOfItems = self.__modelStore.takeRow( existingItem[0].index().row()) self.__modelInventory.appendRow(listOfItems) self.itemBought.emit(listOfItems[0].text(), listOfItems[0].data()) else: newItem = QStandardItem(name) self.__modelInventory.appendRow(newItem) self.itemBought.emit(newItem.text(), newItem.data()) def buyCustomItem(self): """ Fügt dem Inventar des Charakters einen Gegenstand hinzu. \todo Nach dem Drücken des Hinzufügen.Knopfes, sollte der Fokus wieder auf das LineEdit gehen. """ newName = self.ui.lineEdit_custom.text() if newName: self.__customItem(newName) ## Textzeile löschen self.ui.lineEdit_custom.setText("") def sellItem(self): """ Der besagte Gegenstand wird vom Inventar zurück in den Laden befördert. """ listOfItems = self.__modelInventory.takeRow( self.ui.view_inventory.currentIndex().row()) self.__modelStore.appendRow(listOfItems) #for item in listOfItems: #Debug.debug(item.data()) self.itemSold.emit(listOfItems[0].text(), listOfItems[0].data()) def moveItemToInventory(self, name, category=None): """ Der besagte Gegenstand wird aus dem Laden ins Inventar bewegt. Gibt es keinen Gegenstand dieses Namens im Laden, wird er direkt im Inventar erzeugt. """ foundItems = self.__modelStore.findItems(name) if foundItems: for item in foundItems: if item.data() == category: listOfItems = self.__modelStore.takeRow(item.index().row()) self.__modelInventory.appendRow(listOfItems) else: self.__customItem(name) def moveItemToStore(self, name, category=None): """ Der besagte Gegenstand wird aus dem Inventar in den Laden bewegt. """ foundItems = self.__modelInventory.findItems(name) for item in foundItems: if item.data() == category: listOfItems = self.__modelInventory.takeRow(item.index().row()) self.__modelStore.appendRow(listOfItems) def checkButtonState(self): """ Aktiviert/Deaktiviert die Knöpfe für das Übertragen von Gegenständen. """ if self.__modelInventory.rowCount() > 0: self.ui.pushButton_remove.setEnabled(True) else: self.ui.pushButton_remove.setEnabled(False) if self.__modelStore.rowCount() > 0: self.ui.pushButton_add.setEnabled(True) else: self.ui.pushButton_add.setEnabled(False) def changeCustomButtonState(self): """ Aktiviert den Knopf zum Hinzufügen eines zusätzlichen Gegenstandes nur, wenn es etwas zum Hinzufügen gibt. Die zeile also nicht leer und der Gegnstand noch nicht vorhanden ist. """ self.ui.pushButton_addCustom.setEnabled(False) if self.ui.lineEdit_custom.text( ) and not self.__modelInventory.findItems( self.ui.lineEdit_custom.text()): self.ui.pushButton_addCustom.setEnabled(True)
class OWConfusionMatrix(widget.OWWidget): """Confusion matrix widget""" name = "Confusion Matrix" description = "Display a confusion matrix constructed from " \ "the results of classifier evaluations." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [("Evaluation Results", Orange.evaluation.Results, "set_results")] outputs = [("Selected Data", Orange.data.Table)] quantities = [ "Number of instances", "Proportion of predicted", "Proportion of actual" ] settingsHandler = settings.ClassValuesContextHandler() selected_learner = settings.Setting([0], schema_only=True) selection = settings.ContextSetting(set()) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) UserAdviceMessages = [ widget.Message( "Clicking on cells or in headers outputs the corresponding " "data instances", "click_cell") ] def __init__(self): super().__init__() self.data = None self.results = None self.learners = [] self.headers = [] box = gui.vBox(self.controlArea, "Learners") self.learners_box = gui.listBox(box, self, "selected_learner", "learners", callback=self._learner_changed) box = gui.vBox(self.controlArea, "Show") gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.vBox(self.controlArea, "Select") gui.button(box, self, "Select Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Select Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "Clear Selection", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.vBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Probabilities", callback=self._invalidate) gui.auto_commit(self.controlArea, self, "autocommit", "Send Selected", "Send Automatically") grid = QGridLayout() self.tablemodel = QStandardItemModel(self) view = self.tableview = QTableView( editTriggers=QTableView.NoEditTriggers) view.setModel(self.tablemodel) view.horizontalHeader().hide() view.verticalHeader().hide() view.horizontalHeader().setMinimumSectionSize(60) view.selectionModel().selectionChanged.connect(self._invalidate) view.setShowGrid(False) view.setItemDelegate(BorderedItemDelegate(Qt.white)) view.clicked.connect(self.cell_clicked) grid.addWidget(view, 0, 0) self.mainArea.layout().addLayout(grid) def sizeHint(self): """Initial size""" return QSize(750, 490) def _item(self, i, j): return self.tablemodel.item(i, j) or QStandardItem() def _set_item(self, i, j, item): self.tablemodel.setItem(i, j, item) def _init_table(self, nclasses): item = self._item(0, 2) item.setData("Predicted", Qt.DisplayRole) item.setTextAlignment(Qt.AlignCenter) item.setFlags(Qt.NoItemFlags) self._set_item(0, 2, item) item = self._item(2, 0) item.setData("Actual", Qt.DisplayRole) item.setTextAlignment(Qt.AlignHCenter | Qt.AlignBottom) item.setFlags(Qt.NoItemFlags) self.tableview.setItemDelegateForColumn(0, gui.VerticalItemDelegate()) self._set_item(2, 0, item) self.tableview.setSpan(0, 2, 1, nclasses) self.tableview.setSpan(2, 0, nclasses, 1) font = self.tablemodel.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) for i in (0, 1): for j in (0, 1): item = self._item(i, j) item.setFlags(Qt.NoItemFlags) self._set_item(i, j, item) for p, label in enumerate(self.headers): for i, j in ((1, p + 2), (p + 2, 1)): item = self._item(i, j) item.setData(label, Qt.DisplayRole) item.setFont(bold_font) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) if p < len(self.headers) - 1: item.setData("br"[j == 1], BorderRole) item.setData(QColor(192, 192, 192), BorderColorRole) self._set_item(i, j, item) hor_header = self.tableview.horizontalHeader() if len(' '.join(self.headers)) < 120: hor_header.setResizeMode(QHeaderView.ResizeToContents) else: hor_header.setDefaultSectionSize(60) self.tablemodel.setRowCount(nclasses + 3) self.tablemodel.setColumnCount(nclasses + 3) def set_results(self, results): """Set the input results.""" prev_sel_learner = self.selected_learner.copy() self.clear() self.warning() self.closeContext() data = None if results is not None and results.data is not None: data = results.data if data is not None and not data.domain.has_discrete_class: self.warning("Confusion Matrix cannot show regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is None: self.report_button.setDisabled(True) else: self.report_button.setDisabled(False) nmodels = results.predicted.shape[0] self.headers = class_values + \ [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'learner_names' is set in 'Test Learners' widget. if hasattr(results, "learner_names"): self.learners = results.learner_names else: self.learners = [ "Learner #{}".format(i + 1) for i in range(nmodels) ] self._init_table(len(class_values)) self.openContext(data.domain.class_var) if not prev_sel_learner or prev_sel_learner[0] >= len( self.learners): self.selected_learner[:] = [0] else: self.selected_learner[:] = prev_sel_learner self._update() self._set_selection() self.unconditional_commit() def clear(self): """Reset the widget, clear controls""" self.results = None self.data = None self.tablemodel.clear() self.headers = [] # Clear learners last. This action will invoke `_learner_changed` self.learners = [] def select_correct(self): """Select the diagonal elements of the matrix""" selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_wrong(self): """Select the off-diagonal elements of the matrix""" selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_none(self): """Reset selection""" self.tableview.selectionModel().clear() def cell_clicked(self, model_index): """Handle cell click event""" i, j = model_index.row(), model_index.column() if not i or not j: return n = self.tablemodel.rowCount() index = self.tablemodel.index selection = None if i == j == 1 or i == j == n - 1: selection = QItemSelection(index(2, 2), index(n - 1, n - 1)) elif i in (1, n - 1): selection = QItemSelection(index(2, j), index(n - 1, j)) elif j in (1, n - 1): selection = QItemSelection(index(i, 2), index(i, n - 1)) if selection is not None: self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def commit(self): """Output data instances corresponding to selected cells""" if self.results is not None and self.data is not None \ and self.selected_learner: indices = self.tableview.selectedIndexes() indices = {(ind.row() - 2, ind.column() - 2) for ind in indices} actual = self.results.actual learner_name = self.learners[self.selected_learner[0]] predicted = self.results.predicted[self.selected_learner[0]] selected = [ i for i, t in enumerate(zip(actual, predicted)) if t in indices ] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values) metas = metas + (var, ) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[self.selected_learner[0], selected] extra.append(numpy.array(probs, dtype=object)) pvars = [ Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values ] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] row_ids = self.data.ids[row_indices] M = numpy.hstack((M, ) + tuple(extra)) domain = Orange.data.Domain(self.data.domain.attributes, self.data.domain.class_vars, metas) data = Orange.data.Table.from_numpy(domain, X, Y, M) data.ids = row_ids data.name = learner_name else: data = None self.send("Selected Data", data) def _invalidate(self): indices = self.tableview.selectedIndexes() self.selection = {(ind.row() - 2, ind.column() - 2) for ind in indices} self.commit() def _set_selection(self): selection = QItemSelection() index = self.tableview.model().index for row, col in self.selection: sel = index(row + 2, col + 2) selection.select(sel, sel) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def _learner_changed(self): self._update() self._set_selection() self.commit() def _update(self): def _isinvalid(x): return isnan(x) or isinf(x) # Update the displayed confusion matrix if self.results is not None and self.selected_learner: cmatrix = confusion_matrix(self.results, self.selected_learner[0]) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) n = len(cmatrix) diag = numpy.diag_indices(n) colors = cmatrix.astype(numpy.double) colors[diag] = 0 if self.selected_quantity == 0: normalized = cmatrix.astype(numpy.int) formatstr = "{}" div = numpy.array([colors.max()]) else: if self.selected_quantity == 1: normalized = 100 * cmatrix / colsum div = colors.max(axis=0) else: normalized = 100 * cmatrix / rowsum[:, numpy.newaxis] div = colors.max(axis=1)[:, numpy.newaxis] formatstr = "{:2.1f} %" div[div == 0] = 1 colors /= div colors[diag] = normalized[diag] / normalized[diag].max() for i in range(n): for j in range(n): val = normalized[i, j] col_val = colors[i, j] item = self._item(i + 2, j + 2) item.setData( "NA" if _isinvalid(val) else formatstr.format(val), Qt.DisplayRole) bkcolor = QColor.fromHsl( [0, 240][i == j], 160, 255 if _isinvalid(col_val) else int(255 - 30 * col_val)) item.setData(QBrush(bkcolor), Qt.BackgroundRole) item.setData("trbl", BorderRole) item.setToolTip("actual: {}\npredicted: {}".format( self.headers[i], self.headers[j])) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self._set_item(i + 2, j + 2, item) bold_font = self.tablemodel.invisibleRootItem().font() bold_font.setBold(True) def _sum_item(value, border=""): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) item.setData(border, BorderRole) item.setData(QColor(192, 192, 192), BorderColorRole) return item for i in range(n): self._set_item(n + 2, i + 2, _sum_item(int(colsum[i]), "t")) self._set_item(i + 2, n + 2, _sum_item(int(rowsum[i]), "l")) self._set_item(n + 2, n + 2, _sum_item(int(rowsum.sum()))) def send_report(self): """Send report""" if self.results is not None and self.selected_learner: self.report_table( "Confusion matrix for {} (showing {})".format( self.learners[self.selected_learner[0]], self.quantities[self.selected_quantity].lower()), self.tableview)
class OWConfusionMatrix(widget.OWWidget): name = "Confusion Matrix" description = "Display confusion matrix constructed from results " \ "of evaluation of classifiers." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [("Evaluation Results", Orange.evaluation.Results, "set_results")] outputs = [("Selected Data", Orange.data.Table)] quantities = ["Number of instances", "Proportion of predicted", "Proportion of actual"] selected_learner = settings.Setting([]) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) UserAdviceMessages = [ widget.Message( "Clicking on cells or in headers outputs the corresponding " "data instances", "click_cell")] def __init__(self): super().__init__() self.data = None self.results = None self.learners = [] self.headers = [] box = gui.widgetBox(self.controlArea, "Learners") self.learners_box = gui.listBox( box, self, "selected_learner", "learners", callback=self._learner_changed ) box = gui.widgetBox(self.controlArea, "Show") gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.widgetBox(self.controlArea, "Select") gui.button(box, self, "Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "None", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Probabilities", callback=self._invalidate) gui.auto_commit(self.controlArea, self, "autocommit", "Send Data", "Auto send is on") grid = QGridLayout() self.tablemodel = QStandardItemModel(self) view = self.tableview = QTableView( editTriggers=QTableView.NoEditTriggers) view.setModel(self.tablemodel) view.horizontalHeader().hide() view.verticalHeader().hide() view.horizontalHeader().setMinimumSectionSize(60) view.selectionModel().selectionChanged.connect(self._invalidate) view.setShowGrid(False) view.clicked.connect(self.cell_clicked) grid.addWidget(view, 0, 0) self.mainArea.layout().addLayout(grid) def sizeHint(self): return QSize(750, 490) def _item(self, i, j): return self.tablemodel.item(i, j) or QStandardItem() def _set_item(self, i, j, item): self.tablemodel.setItem(i, j, item) def set_results(self, results): """Set the input results.""" self.clear() self.warning([0, 1]) data = None if results is not None: if results.data is not None: data = results.data if data is not None and not data.domain.has_discrete_class: data = None results = None self.warning( 0, "Confusion Matrix cannot be used for regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is not None: nmodels, ntests = results.predicted.shape self.headers = class_values + \ [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'learner_names' is set in 'Test Learners' widget. if hasattr(results, "learner_names"): self.learners = results.learner_names else: self.learners = ["Learner #%i" % (i + 1) for i in range(nmodels)] item = self._item(0, 2) item.setData("Predicted", Qt.DisplayRole) item.setTextAlignment(Qt.AlignCenter) item.setFlags(Qt.NoItemFlags) self._set_item(0, 2, item) item = self._item(2, 0) item.setData("Actual", Qt.DisplayRole) item.setTextAlignment(Qt.AlignHCenter | Qt.AlignBottom) item.setFlags(Qt.NoItemFlags) self.tableview.setItemDelegateForColumn( 0, gui.VerticalItemDelegate()) self._set_item(2, 0, item) self.tableview.setSpan(0, 2, 1, len(class_values)) self.tableview.setSpan(2, 0, len(class_values), 1) for i in (0, 1): for j in (0, 1): item = self._item(i, j) item.setFlags(Qt.NoItemFlags) self._set_item(i, j, item) for p, label in enumerate(self.headers): for i, j in ((1, p + 2), (p + 2, 1)): item = self._item(i, j) item.setData(label, Qt.DisplayRole) item.setData(QBrush(QColor(208, 208, 208)), Qt.BackgroundColorRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) self._set_item(i, j, item) hor_header = self.tableview.horizontalHeader() if len(' '.join(self.headers)) < 120: hor_header.setResizeMode(QHeaderView.ResizeToContents) else: hor_header.setDefaultSectionSize(60) self.tablemodel.setRowCount(len(class_values) + 3) self.tablemodel.setColumnCount(len(class_values) + 3) self.selected_learner = [0] self._update() def clear(self): self.results = None self.data = None self.tablemodel.clear() self.headers = [] # Clear learners last. This action will invoke `_learner_changed` # method self.learners = [] def select_correct(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) def select_wrong(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) def select_none(self): self.tableview.selectionModel().clear() def cell_clicked(self, model_index): i, j = model_index.row(), model_index.column() if not i or not j: return n = self.tablemodel.rowCount() index = self.tablemodel.index selection = None if i == j == 1 or i == j == n - 1: selection = QItemSelection(index(2, 2), index(n - 1, n - 1)) elif i in (1, n - 1): selection = QItemSelection(index(2, j), index(n - 1, j)) elif j in (1, n - 1): selection = QItemSelection(index(i, 2), index(i, n - 1)) if selection is not None: self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) def commit(self): if self.results is not None and self.data is not None \ and self.selected_learner: indices = self.tableview.selectedIndexes() indices = {(ind.row() - 2, ind.column() - 2) for ind in indices} actual = self.results.actual selected_learner = self.selected_learner[0] learner_name = self.learners[selected_learner] predicted = self.results.predicted[selected_learner] selected = [i for i, t in enumerate(zip(actual, predicted)) if t in indices] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values ) metas = metas + (var,) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[selected_learner, selected] extra.append(numpy.array(probs, dtype=object)) pvars = [Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] row_ids = self.data.ids[row_indices] M = numpy.hstack((M,) + tuple(extra)) domain = Orange.data.Domain( self.data.domain.attributes, self.data.domain.class_vars, metas ) data = Orange.data.Table.from_numpy(domain, X, Y, M) data.ids = row_ids data.name = learner_name else: data = None self.send("Selected Data", data) def _invalidate(self): self.commit() def _learner_changed(self): # The selected learner has changed indices = self.tableview.selectedIndexes() self._update() selection = QItemSelection() for sel in indices: selection.select(sel, sel) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) self.commit() def _update(self): # Update the displayed confusion matrix if self.results is not None and self.selected_learner: index = self.selected_learner[0] cmatrix = confusion_matrix(self.results, index) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) total = rowsum.sum() if self.selected_quantity == 0: value = lambda i, j: int(cmatrix[i, j]) elif self.selected_quantity == 1: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i]) if colsum[i] else "N/A") elif self.selected_quantity == 2: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i]) if colsum[i] else "N/A") else: assert False for i, row in enumerate(cmatrix): for j, _ in enumerate(row): item = self._item(i + 2, j + 2) item.setData(value(i, j), Qt.DisplayRole) item.setToolTip("actual: {}\npredicted: {}".format( self.headers[i], self.headers[j])) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self._set_item(i + 2, j + 2, item) model = self.tablemodel font = model.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) def sum_item(value): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) return item N = len(colsum) for i in range(N): model.setItem(N + 2, i + 2, sum_item(int(colsum[i]))) model.setItem(i + 2, N + 2, sum_item(int(rowsum[i]))) model.setItem(N + 2, N + 2, sum_item(int(total)))
class Terminals(QWidget): ready = pyqtSignal(bool) def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = uic.loadUiType('terminal.ui')[0]() self.ui.setupUi(self) self.notifier = QSystemTrayIcon(QIcon('arrow-up-icon.png'), self) self.notifier.show() self.session = None self.model = None self.devices = {} self.mainloop = None self.delegate = None def test_display(self): if self.mainloop: self.mainloop.test_display() def update_device_config(self): if self.mainloop: self.mainloop.update_config() def terminal_open(self, addr): if self.mainloop: self.mainloop.terminal_open(addr) def terminal_close(self, addr): if self.mainloop: self.mainloop.terminal_close(addr) def begin_session(self, fio, access): if access in ['operator']: self.ui.cashier.setText(fio) self.session = (fio, access) return True return False def end_session(self, block=False): self.ui.cashier.setText(u'') self.session = None self.stop_mainloop(block) return True def on_mainloop_stopped(self): self.mainloop = None if self.session: self.start_mainloop() def start_mainloop(self): if self.mainloop is None: self.mainloop = Mainloop(devices=self.devices) self.mainloop.ready.connect(self.on_mainloop_ready) self.mainloop.stopped.connect(self.on_mainloop_stopped) self.mainloop.notify.connect(lambda title, msg: self.notifier.showMessage(title, msg)) self.mainloop.start() def stop_mainloop(self, block=False): if self.mainloop: try: self.mainloop.state.disconnect() self.mainloop.ready.disconnect() self.mainloop.notify.disconnect() except TypeError: print 'NOTE: mainloop signals disconnect' if self.model: [self.ui.terminals.closePersistentEditor(self.model.index(row, 0)) for row in xrange(self.model.rowCount())] self.mainloop.stop(block) else: self.ready.emit(False) def reset_mainloop(self, devices): self.devices = devices if self.mainloop is None: self.start_mainloop() else: self.stop_mainloop() def on_mainloop_ready(self, ok, titles): if ok: self.model = QStandardItemModel(len(titles), 1) [self.model.setItem(i, QStandardItem(str(addr))) for i, addr in enumerate(titles.keys())] self.delegate = TerminalDelegate(self.mainloop, titles) self.mainloop.report.connect(self.delegate.report) self.mainloop.state.connect(self.delegate.state) self.ui.terminals.setModel(self.model) self.ui.terminals.setItemDelegateForColumn(0, self.delegate) [self.ui.terminals.openPersistentEditor(self.model.index(row, 0)) for row in xrange(self.model.rowCount())] self.mainloop.db.free_places_update.connect(self.ui.free_places.setValue) self.mainloop.update_config() else: self.model = None self.mainloop = None self.ready.emit(ok)
class QgsAttributeTableDialog(QDialog): ''' classdocs ''' def __init__(self, parent, vectorlayer): QDialog.__init__(self, parent) # self.w = QDialog(self) self.baseLayer = vectorlayer self.canChangeAttributes = self.validate( QgsVectorDataProvider.ChangeAttributeValues) self.canDeleteFeatures = self.validate( QgsVectorDataProvider.DeleteFeatures) self.canAddAttributes = self.validate( QgsVectorDataProvider.AddAttributes) self.canDeleteAttributes = self.validate( QgsVectorDataProvider.DeleteAttributes) self.canAddFeatures = self.validate(QgsVectorDataProvider.AddFeatures) gridLayout = QGridLayout(self) self.setLayout(gridLayout) self.setWindowTitle("Attribute Table") self.setFixedSize(QSize(800, 600)) editorToolbar = QToolBar() editorToolbar.setFixedSize(QSize(768, 48)) self.actionToggleEditing = QAction(QIcon("Resource\\edit.png"), "ToggleEditing", self) self.actionToggleEditing.triggered.connect(self.toggleEditing) if (self.canChangeAttributes or self.canDeleteFeatures or self.canAddAttributes or self.canDeleteAttributes or self.canAddFeatures) and (not self.baseLayer.isReadOnly()): self.actionToggleEditing.setEnabled(True) else: self.actionToggleEditing.setEnabled(False) self.actionToggleEditing.setCheckable(True) editorToolbar.addAction(self.actionToggleEditing) self.actionSave = QAction(QIcon("Resource\\filesave.png"), "Save Edits", self) self.actionSave.triggered.connect(self.saveEditing) self.actionSave.setCheckable(False) self.actionSave.setEnabled(False) editorToolbar.addAction(self.actionSave) self.actiondeleteRows = QAction( QIcon("Resource\\mActionDeleteSelected.png"), "Delete selected features", self) self.actiondeleteRows.triggered.connect(self.deleteRows) self.actiondeleteRows.setCheckable(False) self.actiondeleteRows.setEnabled(False) editorToolbar.addAction(self.actiondeleteRows) self.actionUnselectAll = QAction( QIcon("Resource\\mActionDeselectAll.png"), "Unselect All", self) self.actionUnselectAll.triggered.connect(self.unselectAll) self.actionUnselectAll.setCheckable(False) self.actionUnselectAll.setEnabled(True) editorToolbar.addAction(self.actionUnselectAll) self.actionSelectedToZoom = QAction( QIcon("Resource\\mActionZoomToSelected.png"), "Zoom map to the selected rows", self) self.actionSelectedToZoom.triggered.connect(self.selectedToZoom) self.actionSelectedToZoom.setCheckable(False) self.actionSelectedToZoom.setEnabled(True) editorToolbar.addAction(self.actionSelectedToZoom) gridLayout.addWidget(editorToolbar, 0, 0, 1, 1) self.model = QStandardItemModel() # self.model.itemChanged.connect(self.attributeChanged) self.attributeTable = QTableView(self) self.attributeTable.setModel(self.model) self.attributeTable.setColumnWidth(0, 200) self.attributeTable.setColumnWidth(1, 160) self.attributeTable.clicked.connect(self.tableSelectionChanged) self.attributeTable.setSortingEnabled(True) self.changeItemList = [] self.selectRows = [] self.isSave = True self.initTable() gridLayout.addWidget(self.attributeTable, 1, 0, 1, 1) # self.attributeTable.selectionChanged.connect(self.selectFeature) def tableSelectionChanged(self): idxList = self.attributeTable.selectedIndexes() if idxList != None and len(idxList) > 0: self.baseLayer.removeSelection() fidList = [] for idx in idxList: fid = int(self.model.item(idx.row()).text()) fidList.append(fid) self.baseLayer.setSelectedFeatures(fidList) def toggleEditing(self): if self.baseLayer != None: if not self.actionToggleEditing.isChecked(): if self.isSave: self.baseLayer.commitChanges() self.actionSave.setEnabled(False) self.actiondeleteRows.setEnabled(False) self.model.itemChanged.disconnect(self.attributeChanged) self.toggleEditingTable(False) else: button = QMessageBox.warning( self, "Stop Editing", "Do you want to save the changes to layer?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if (button == QMessageBox.Cancel): self.actionToggleEditing.setChecked(True) elif button == QMessageBox.Save: self.saveEditing() self.baseLayer.commitChanges() self.actionSave.setEnabled(False) self.actiondeleteRows.setEnabled(False) self.model.itemChanged.disconnect( self.attributeChanged) self.toggleEditingTable(False) else: self.initTable() self.baseLayer.commitChanges() self.actionSave.setEnabled(False) self.actiondeleteRows.setEnabled(False) self.model.itemChanged.disconnect( self.attributeChanged) self.toggleEditingTable(False) # self.isEditable = False else: self.actionSave.setEnabled(True) self.actiondeleteRows.setEnabled(True) self.baseLayer.startEditing() self.toggleEditingTable(True) self.model.itemChanged.connect(self.attributeChanged) # self.isEditable = True def toggleEditingTable(self, isEditable): columnCount = self.model.columnCount() rowCount = self.model.rowCount() col = 0 while col < columnCount: row = 0 while row < rowCount: self.model.item(row, col).setEditable(isEditable) row += 1 col += 1 def attributeChanged(self, standardItem): self.isSave = False # if not self.isDelete: self.changeItemList.append(standardItem) # featureId = standardItem.row() # self.baseLayer.changeAttributeValue(featureId, # standardItem.column(), standardItem.text()) def saveEditing(self): self.isSave = True if len(self.changeItemList) > 0: for standardItem in self.changeItemList: featureId = standardItem.row() self.baseLayer.changeAttributeValue(featureId, standardItem.column(), standardItem.text()) self.changeItemList = [] if len(self.selectRows) > 0: for id in self.selectRows: self.baseLayer.deleteFeature(id) self.selectRows = [] def initTable(self): self.model.clear() # header = QHeaderView(Qt.Horizontal) # headerModel = QStandardItemModel() layer = self.baseLayer fields = layer.pendingFields() headersList = ["fid"] for field in fields: headersList.append(field.name()) self.model.setHorizontalHeaderLabels(headersList) # headerModel.setHorizontalHeaderLabels(headersList) # header.setModel(headerModel) # self.attributeTable.setHorizontalHeader(header) if len(layer.selectedFeatures()) > 0: features = layer.selectedFeatures() else: features = layer.getFeatures() for feature in features: record = [QStandardItem(str(feature.id()))] for field in feature.fields(): name = field.name() attribute = feature.attribute(name).toString() stdItemValue = QStandardItem(attribute) stdItemValue.setEditable(False) record.append(stdItemValue) self.model.appendRow(record) def deleteRows(self): if len(self.attributeTable.selectedIndexes()) > 0: self.isSave = False selectedIndexs = self.attributeTable.selectedIndexes() k = -1 self.selectRows = [] for index in selectedIndexs: if k != index.row(): k = index.row() self.selectRows.append(k) for row in self.selectRows: self.model.takeRow(row) def unselectAll(self): if len(self.attributeTable.selectedIndexes()) > 0: self.attributeTable.clearSelection() def selectedToZoom(self): if len(self.attributeTable.selectedIndexes()) > 0: self.baseLayer.removeSelection() selectedIndexs = self.attributeTable.selectedIndexes() k = -1 self.selectRows = [] for index in selectedIndexs: if k != index.row(): k = index.row() self.selectRows.append(k) self.baseLayer.setSelectedFeatures(self.selectRows) # for row in self.selectRows: # self.model.takeRow(row) define._canvas.zoomToSelected(self.baseLayer) def validate(self, condition): if self.baseLayer.dataProvider().capabilities() & condition: return True else: return False
class AbstractStoreWidget(QWidget): """ @brief Ein einfaches Widget, um das Inventar des Charakters zu füllen. """ itemBought = Signal(str, str) itemSold = Signal(str, str) def __init__(self, template, character, parent=None): super(AbstractStoreWidget, self).__init__(parent) self.ui = Ui_AbstractStoreWidget() self.ui.setupUi(self) self.__character = character self.__storage = template self.__modelInventory = QStandardItemModel() self.ui.view_inventory.setModel(self.__modelInventory) self.__modelStore = QStandardItemModel() self.ui.view_store.setModel(self.__modelStore) ## Resources self.ui.traitDots_resources.valueChanged.connect(self.__character.traits["Merit"]["Social"]["Resources"].setValue) self.__character.traits["Merit"]["Social"]["Resources"].valueChanged.connect(self.ui.traitDots_resources.setValue) self.ui.traitDots_enhancedItem.valueChanged.connect(self.__character.traits["Merit"]["Item"]["Enhanced Item"].setValue) self.__character.traits["Merit"]["Item"]["Enhanced Item"].valueChanged.connect(self.ui.traitDots_enhancedItem.setValue) ## Items self.ui.traitDots_token.maximum = 10 self.ui.traitDots_imbuedItem.maximum = 10 self.ui.traitDots_artifact.maximum = 10 self.ui.traitDots_cursedItem.valueChanged.connect(self.__character.traits["Merit"]["Item"]["Cursed Item"].setValue) self.ui.traitDots_fetish.valueChanged.connect(self.__character.traits["Merit"]["Item"]["Fetish"].setValue) self.ui.traitDots_token.valueChanged.connect(self.__character.traits["Merit"]["Item"]["Token"].setValue) self.ui.traitDots_imbuedItem.valueChanged.connect(self.__character.traits["Merit"]["Item"]["Imbued Item"].setValue) self.ui.traitDots_artifact.valueChanged.connect(self.__character.traits["Merit"]["Item"]["Artifact"].setValue) self.__character.traits["Merit"]["Item"]["Cursed Item"].valueChanged.connect(self.ui.traitDots_cursedItem.setValue) self.__character.traits["Merit"]["Item"]["Fetish"].valueChanged.connect(self.ui.traitDots_fetish.setValue) self.__character.traits["Merit"]["Item"]["Token"].valueChanged.connect(self.ui.traitDots_token.setValue) self.__character.traits["Merit"]["Item"]["Imbued Item"].valueChanged.connect(self.ui.traitDots_imbuedItem.setValue) self.__character.traits["Merit"]["Item"]["Artifact"].valueChanged.connect(self.ui.traitDots_artifact.setValue) self.ui.pushButton_add.setIcon(QIcon(":/icons/images/actions/1leftarrow.png")) self.ui.pushButton_remove.setIcon(QIcon(":/icons/images/actions/1rightarrow.png")) self.__modelInventory.rowsInserted.connect(self.checkButtonState) self.__modelInventory.rowsRemoved.connect(self.checkButtonState) self.__modelStore.rowsInserted.connect(self.checkButtonState) self.__modelStore.rowsRemoved.connect(self.checkButtonState) self.ui.pushButton_add.clicked.connect(self.buyItem) self.ui.view_store.doubleClicked.connect(self.buyItem) self.ui.pushButton_remove.clicked.connect(self.sellItem) self.ui.view_inventory.doubleClicked.connect(self.sellItem) self.ui.lineEdit_custom.textChanged.connect(self.changeCustomButtonState) self.ui.pushButton_addCustom.clicked.connect(self.buyCustomItem) def setEnhancedItemTraitsVisible(self, sw=True): self.ui.label_enhancedItem.setVisible(sw) self.ui.traitDots_enhancedItem.setVisible(sw) def setMagicalItemTraitsVisible(self, sw=True): self.ui.label_cursedItem.setVisible(sw) self.ui.traitDots_cursedItem.setVisible(sw) self.ui.label_fetish.setVisible(sw) self.ui.traitDots_fetish.setVisible(sw) self.ui.label_token.setVisible(sw) self.ui.traitDots_token.setVisible(sw) self.ui.label_artifact.setVisible(sw) self.ui.traitDots_artifact.setVisible(sw) self.ui.label_imbuedItem.setVisible(sw) self.ui.traitDots_imbuedItem.setVisible(sw) def setAddCustomVisible(self, sw=True): self.ui.widget_custom.setVisible(sw) def addItemToStore(self, name, category=None, icon=None): newItem = QStandardItem(name) if icon: newItem.setIcon(icon) if category: newItem.setData(category) self.__modelStore.appendRow(newItem) def buyItem(self): """ Der besagte Gegenstand wird vom Laden in das Inventar übernommen. """ listOfItems = self.__modelStore.takeRow(self.ui.view_store.currentIndex().row()) self.__modelInventory.appendRow(listOfItems) self.itemBought.emit(listOfItems[0].text(), listOfItems[0].data()) def __customItem(self, name): """ Erzeugt einen vom Benutzer benannten Gegenstand. """ if name: existingItemInventory = self.__modelInventory.findItems(name) if not existingItemInventory: existingItem = self.__modelStore.findItems(name) if existingItem: listOfItems = self.__modelStore.takeRow(existingItem[0].index().row()) self.__modelInventory.appendRow(listOfItems) self.itemBought.emit(listOfItems[0].text(), listOfItems[0].data()) else: newItem = QStandardItem(name) self.__modelInventory.appendRow(newItem) self.itemBought.emit(newItem.text(), newItem.data()) def buyCustomItem(self): """ Fügt dem Inventar des Charakters einen Gegenstand hinzu. \todo Nach dem Drücken des Hinzufügen.Knopfes, sollte der Fokus wieder auf das LineEdit gehen. """ newName = self.ui.lineEdit_custom.text() if newName: self.__customItem(newName) ## Textzeile löschen self.ui.lineEdit_custom.setText("") def sellItem(self): """ Der besagte Gegenstand wird vom Inventar zurück in den Laden befördert. """ listOfItems = self.__modelInventory.takeRow(self.ui.view_inventory.currentIndex().row()) self.__modelStore.appendRow(listOfItems) #for item in listOfItems: #Debug.debug(item.data()) self.itemSold.emit(listOfItems[0].text(), listOfItems[0].data()) def moveItemToInventory(self, name, category=None): """ Der besagte Gegenstand wird aus dem Laden ins Inventar bewegt. Gibt es keinen Gegenstand dieses Namens im Laden, wird er direkt im Inventar erzeugt. """ foundItems = self.__modelStore.findItems(name) if foundItems: for item in foundItems: if item.data() == category: listOfItems = self.__modelStore.takeRow(item.index().row()) self.__modelInventory.appendRow(listOfItems) else: self.__customItem(name) def moveItemToStore(self, name, category=None): """ Der besagte Gegenstand wird aus dem Inventar in den Laden bewegt. """ foundItems = self.__modelInventory.findItems(name) for item in foundItems: if item.data() == category: listOfItems = self.__modelInventory.takeRow(item.index().row()) self.__modelStore.appendRow(listOfItems) def checkButtonState(self): """ Aktiviert/Deaktiviert die Knöpfe für das Übertragen von Gegenständen. """ if self.__modelInventory.rowCount() > 0: self.ui.pushButton_remove.setEnabled(True) else: self.ui.pushButton_remove.setEnabled(False) if self.__modelStore.rowCount() > 0: self.ui.pushButton_add.setEnabled(True) else: self.ui.pushButton_add.setEnabled(False) def changeCustomButtonState(self): """ Aktiviert den Knopf zum Hinzufügen eines zusätzlichen Gegenstandes nur, wenn es etwas zum Hinzufügen gibt. Die zeile also nicht leer und der Gegnstand noch nicht vorhanden ist. """ self.ui.pushButton_addCustom.setEnabled(False) if self.ui.lineEdit_custom.text() and not self.__modelInventory.findItems(self.ui.lineEdit_custom.text()): self.ui.pushButton_addCustom.setEnabled(True)
class TemporalSpectralProfilePlugin: POINT_SELECTION = 0 SELECTED_POLYGON = 1 def __init__(self, iface): self.iface = iface self.canvas = iface.mapCanvas() self.wdg = None self.pointTool = None def initGui(self): # create action self.action = QAction( QIcon( ":/plugins/temporalprofiletool/icons/temporalProfileIcon.png"), "Temporal/Spectral Profile", self.iface.mainWindow()) self.action.setWhatsThis("Plots temporal/spectral profiles") QObject.connect(self.action, SIGNAL("triggered()"), self.run) self.aboutAction = QAction("About", self.iface.mainWindow()) QObject.connect(self.aboutAction, SIGNAL("triggered()"), self.about) # add toolbar button and menu item self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu("&Profile Tool", self.action) self.iface.addPluginToMenu("&Profile Tool", self.aboutAction) #Init class variables self.pointTool = ProfiletoolMapTool(self.iface.mapCanvas(), self.action) #the mouselistener self.dockOpened = False #remember for not reopening dock if there's already one opened self.pointstoDraw = None #Polyline in mapcanvas CRS analysed self.dblclktemp = None #enable disctinction between leftclick and doubleclick self.mdl = None #the model whitch in are saved layers analysed caracteristics self.selectionmethod = 0 #The selection method defined in option self.saveTool = self.canvas.mapTool( ) #Save the standard mapttool for restoring it at the end self.plotlibrary = None #The plotting library to use self.pointSelectionInstructions = "Click on a raster for temporal/spectral profile (right click to cancel then quit)" self.selectedPolygonInstructions = 'Use "Select Features" tool to select polygon(s) designating AOI for which temporal/spectral profile should be calculated' def unload(self): if not self.wdg is None: self.wdg.close() self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu("&Profile Tool", self.action) self.iface.removePluginMenu("&Profile Tool", self.aboutAction) def run(self): # first, check posibility if self.checkIfOpening() == False: return #if dock not already opened, open the dock and all the necessary thing (model,doProfile...) if self.dockOpened == False: self.mdl = QStandardItemModel(0, 6) self.wdg = PTDockWidget(self.iface.mainWindow(), self.iface, self.mdl) self.wdg.showIt() self.doprofile = DoProfile(self.iface, self.wdg, self.pointTool, self) self.tableViewTool = TableViewTool() QObject.connect(self.wdg, SIGNAL("closed(PyQt_PyObject)"), self.cleaning2) QObject.connect(self.wdg.tableView, SIGNAL("clicked(QModelIndex)"), self._onClick) QObject.connect(self.wdg.pushButton_2, SIGNAL("clicked()"), self.addLayer) QObject.connect(self.wdg.pushButton, SIGNAL("clicked()"), self.removeLayer) QObject.connect(self.wdg.comboBox, SIGNAL("currentIndexChanged(int)"), self.selectionMethod) QObject.connect(self.wdg.cboLibrary, SIGNAL("currentIndexChanged(int)"), self.changePlotLibrary) QObject.connect(self.wdg.cboXAxis, SIGNAL("currentIndexChanged(int)"), self.changeXAxisLabeling) QObject.connect(self.wdg.leXAxisSteps, SIGNAL("editingFinished()"), self.changeXAxisLabeling) QObject.connect(self.wdg.dateTimeEditCurrentTime, SIGNAL("editingFinished()"), self.changeXAxisLabeling) QObject.connect(self.wdg.spinBoxTimeExtent, SIGNAL("editingFinished()"), self.changeXAxisLabeling) QObject.connect(self.wdg.cboTimeExtent, SIGNAL("currentIndexChanged(int)"), self.changeXAxisLabeling) QObject.connect(self.wdg.cbTimeDimension, SIGNAL("stateChanged(int)"), self.changeXAxisLabeling) self.wdg.addOptionComboboxItems() self.addLayer() self.dockOpened = True #Listeners of mouse self.connectPointMapTool() #init the mouse listener comportement and save the classic to restore it on quit self.canvas.setMapTool(self.pointTool) #Help about what doing if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.iface.mainWindow().statusBar().showMessage( self.pointSelectionInstructions) elif self.selectionmethod == TemporalSpectralProfilePlugin.SELECTED_POLYGON: self.iface.mainWindow().statusBar().showMessage( self.selectedPolygonInstructions) QObject.connect(QgsMapLayerRegistry.instance(), SIGNAL("layersWillBeRemoved (QStringList)"), self.onLayersWillBeRemoved) #************************************* Canvas listener actions ********************************************** # Used when layer is about to be removed from QGIS Map Layer Registry def onLayersWillBeRemoved(self, layersIds): if self.mdl is not None: for layerId in layersIds: for row in range(self.mdl.rowCount()): if layerId == self.mdl.index(row, 3).data().id(): self.removeLayer(row) self.onLayersWillBeRemoved(layersIds) break # Use for selected polygon option def selectionChanged(self, layer): if not layer.geometryType() == QGis.Polygon: return fullGeometry = QgsGeometry() for feature in layer.selectedFeatures(): if fullGeometry.isEmpty(): fullGeometry = QgsGeometry(feature.constGeometry()) else: fullGeometry = fullGeometry.combine(feature.constGeometry()) if not fullGeometry.isEmpty(): crs = osr.SpatialReference() crs.ImportFromProj4(str(layer.crs().toProj4())) self.doprofile.calculatePolygonProfile(fullGeometry, crs, self.mdl, self.plotlibrary) #************************************* Mouse listener actions *********************************************** # Used for point selection option def moved(self, point): if self.wdg and not self.wdg.cbPlotWhenClick.isChecked(): if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.doubleClicked(point) if self.selectionmethod == TemporalSpectralProfilePlugin.SELECTED_POLYGON: pass def rightClicked(self, point): #used to quit the current action self.cleaning() def leftClicked(self, point): self.doubleClicked(point) def doubleClicked(self, point): if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.iface.mainWindow().statusBar().showMessage( str(point.x()) + ", " + str(point.y())) self.doprofile.calculatePointProfile(point, self.mdl, self.plotlibrary) if self.selectionmethod == TemporalSpectralProfilePlugin.SELECTED_POLYGON: return #***************************** open and quit options ******************************************* def checkIfOpening(self): if self.iface.mapCanvas().layerCount() == 0: #Check a layer is opened QMessageBox.warning(self.iface.mainWindow(), "Profile", "First open a raster layer, please") return False layer = self.iface.activeLayer() if layer == None or not isProfilable( layer): #Check if a raster layer is opened and selected if self.mdl == None or self.mdl.rowCount() == 0: QMessageBox.warning(self.iface.mainWindow(), "Profile Tool", "Please select a raster layer") return False return True def connectPointMapTool(self): QObject.connect(self.pointTool, SIGNAL("moved"), self.moved) QObject.connect(self.pointTool, SIGNAL("rightClicked"), self.rightClicked) QObject.connect(self.pointTool, SIGNAL("leftClicked"), self.leftClicked) QObject.connect(self.pointTool, SIGNAL("doubleClicked"), self.doubleClicked) QObject.connect(self.pointTool, SIGNAL("deactivate"), self.deactivatePointMapTool) def deactivatePointMapTool(self): #enable clean exit of the plugin QObject.disconnect(self.pointTool, SIGNAL("moved"), self.moved) QObject.disconnect(self.pointTool, SIGNAL("leftClicked"), self.leftClicked) QObject.disconnect(self.pointTool, SIGNAL("rightClicked"), self.rightClicked) QObject.disconnect(self.pointTool, SIGNAL("doubleClicked"), self.doubleClicked) self.iface.mainWindow().statusBar().showMessage("") def connectSelectedPolygonsTool(self): QObject.connect(self.iface.mapCanvas(), SIGNAL("selectionChanged(QgsMapLayer *)"), self.selectionChanged) def deactivateSelectedPolygonsTools(self): QObject.disconnect(self.iface.mapCanvas(), SIGNAL("selectionChanged(QgsMapLayer *)"), self.selectionChanged) def cleaning(self): #used on right click self.canvas.unsetMapTool(self.pointTool) self.canvas.setMapTool(self.saveTool) self.iface.mainWindow().statusBar().showMessage("") def cleaning2(self): #used when Dock dialog is closed QObject.disconnect(self.wdg.tableView, SIGNAL("clicked(QModelIndex)"), self._onClick) if self.selectionmethod == TemporalSpectralProfilePlugin.POINT_SELECTION: self.deactivatePointMapTool() else: self.deactivateSelectedPolygonsTools() self.selectionmethod = TemporalSpectralProfilePlugin.POINT_SELECTION QObject.disconnect(self.wdg.comboBox, SIGNAL("currentIndexChanged(int)"), self.selectionMethod) QObject.disconnect(QgsMapLayerRegistry.instance(), SIGNAL("layersWillBeRemoved (QStringList)"), self.onLayersWillBeRemoved) self.mdl = None self.dockOpened = False self.cleaning() self.wdg = None #***************************** Options ******************************************* def selectionMethod(self, item): if item == TemporalSpectralProfilePlugin.POINT_SELECTION: self.selectionmethod = TemporalSpectralProfilePlugin.POINT_SELECTION self.pointTool.setCursor(Qt.CrossCursor) self.deactivateSelectedPolygonsTools() self.connectPointMapTool() if not self.canvas.mapTool() == self.pointTool: self.canvas.setMapTool(self.pointTool) self.iface.mainWindow().statusBar().showMessage( self.pointSelectionInstructions) self.wdg.changeStatComboBoxItems( self.doprofile.getPointProfileStatNames()) elif item == TemporalSpectralProfilePlugin.SELECTED_POLYGON: self.selectionmethod = TemporalSpectralProfilePlugin.SELECTED_POLYGON self.deactivatePointMapTool() self.connectSelectedPolygonsTool() self.iface.actionSelectRectangle().trigger() self.iface.mainWindow().statusBar().showMessage( self.selectedPolygonInstructions) self.wdg.changeStatComboBoxItems( self.doprofile.getPolygonProfileStatNames(), "mean") def changePlotLibrary(self, item): self.plotlibrary = self.wdg.cboLibrary.itemText(item) self.wdg.addPlotWidget(self.plotlibrary) self.changeXAxisLabeling() def changeXAxisLabeling(self): self.xAxisSteps = {} # default band number labeling if self.wdg.cboXAxis.currentIndex() == 0: self.doprofile.xAxisSteps = None # Labels from string elif self.wdg.cboXAxis.currentIndex() == 1: self.doprofile.xAxisSteps = self.wdg.leXAxisSteps.text().split(';') try: self.doprofile.xAxisSteps = [ float(x) for x in self.doprofile.xAxisSteps ] except ValueError: self.doprofile.xAxisSteps = None text = "Temporal/Spectral Profile Tool: The X-axis steps' string " + \ "is invalid. Using band numbers instead." self.iface.messageBar().pushWidget( self.iface.messageBar().createMessage(text), QgsMessageBar.WARNING, 5) # Labels based on time elif self.wdg.cboXAxis.currentIndex() == 2: self.doprofile.xAxisSteps = [ "Timesteps", self.wdg.dateTimeEditCurrentTime.dateTime().toPyDateTime(), int(self.wdg.spinBoxTimeExtent.cleanText()), self.wdg.cboTimeExtent.currentText(), self.wdg.cbTimeDimension.isChecked() ] if self.plotlibrary == "Qwt5": text = "Temporal/Spectral Profile Tool: There is currently no support using " + \ "Time steps while using the Qwt plotlibrary" self.iface.messageBar().pushWidget( self.iface.messageBar().createMessage(text), QgsMessageBar.WARNING, 5) self.doprofile.xAxisSteps = None #************************* tableview function ****************************************** def addLayer(self): layer = self.iface.activeLayer() if isProfilable(layer): self.tableViewTool.addLayer(self.iface, self.mdl, layer) def _onClick(self, index1): #action when clicking the tableview self.tableViewTool.onClick(self.iface, self.wdg, self.mdl, self.plotlibrary, index1) def removeLayer(self, index=None): if index is None: index = self.tableViewTool.chooseLayerForRemoval( self.iface, self.mdl) if index is not None: self.tableViewTool.removeLayer(self.mdl, index) PlottingTool().clearData(self.wdg, self.mdl, self.plotlibrary) def about(self): from ui.dlgabout import DlgAbout DlgAbout(self.iface.mainWindow()).exec_()
class LogDialog(QDialog): """LogDialog for the Freeseer project. It is the dialog window for the log. There is an instance for every FreeseerApp. It has a LogHandler which calls LogDialog's message() method when a new log message is received. The call to message() causes a call to add_entry() which adds the information to a new row in the table. """ def __init__(self, parent=None): super(LogDialog, self).__init__(parent) self.resize(800, 500) self.app = QApplication.instance() icon = QIcon() icon.addPixmap(QPixmap(_fromUtf8(":/freeseer/logo.png")), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) layout = QVBoxLayout() self.setLayout(layout) self.level = 0 self.handler = LogHandler() self.table_model = QStandardItemModel(0, 5) header_names = ["Date", "Level", "Module", "Message", "LevelNo"] date_column = header_names.index("Date") level_column = header_names.index("Level") module_column = header_names.index("Module") self.level_num_column = header_names.index("LevelNo") self.table_model.setHorizontalHeaderLabels(header_names) self.table_view = QTableView() self.table_view.setModel(self.table_model) self.table_view.horizontalHeader().setStretchLastSection(True) self.table_view.setColumnWidth(date_column, 125) self.table_view.setColumnWidth(level_column, 60) self.table_view.setColumnWidth(module_column, 250) self.table_view.setColumnHidden(self.level_num_column, True) self.table_view.setShowGrid(False) self.table_view.horizontalHeader().setClickable(False) self.table_view.verticalHeader().hide() self.table_view.setStyleSheet("""Qtable_view::item { border-bottom: 1px solid lightgrey; selection-background-color: white; selection-color: black; }""") top_panel = QHBoxLayout() self.log_levels = ["Debug", "Info", "Warning", "Error"] self.level_colors = ["#3E4C85", "#269629", "#B0AB21", "#B32020"] self.levels_label = QLabel("Filter Level: ") self.levels_label.setStyleSheet("QLabel { font-weight: bold }") self.current_level_label = QLabel(self.log_levels[0]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format(self.level_colors[0])) self.clear_button = QPushButton("Clear Log") self.levels_slider = QSlider(Qt.Horizontal) self.levels_slider.setStyleSheet(""" QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #E3E3E3); border: 1px solid #707070; width: 10px; margin-top: -4px; margin-bottom: -4px; border-radius: 4px; } QSlider::handle:horizontal:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #DEDEDE, stop:1 #C9C9C9); border: 1px solid #4F4F4F; border-radius: 4px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BFBFBF, stop: 1 #9E9E9E); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #9E9E9E, stop: 1 #858585); border: 1px solid #777; height: 10px; border-radius: 4px; } QSlider::add-page:horizontal { background: #fff; border: 1px solid #707070; height: 10px; border-radius: 4px; }""") self.levels_slider.setRange(0, len(self.log_levels) - 1) self.levels_slider.setTickPosition(QSlider.TicksBelow) self.levels_slider.setTickInterval(1) top_panel.addSpacerItem(QSpacerItem(10, 0)) top_panel.addWidget(self.levels_label, 3) top_panel.addWidget(self.current_level_label, 2) top_panel.addWidget(self.levels_slider, 8) top_panel.addSpacerItem(QSpacerItem(25, 0)) top_panel.addWidget(self.clear_button, 10) layout.addLayout(top_panel) layout.addWidget(self.table_view) self.connect(self.clear_button, SIGNAL('clicked()'), functools.partial(self.table_model.setRowCount, 0)) self.connect(self.levels_slider, SIGNAL('valueChanged(int)'), self.slider_set_level) self.setWindowTitle("Log") self.handler.add_listener(self) def __del__(self): self.handler.remove_listener(self) def retranslate(self): self.setWindowTitle(self.app.translate("LogDialog", "Log")) self.clear_button.setText(self.app.translate("LogDialog", "Clear Log")) self.levels_label.setText("{}: ".format(self.app.translate("LogDialog", "Filter Level"))) def message(self, message): """Passes the log fields to add_entry() It is called by LogHandler when a log message is received""" self.add_entry(message["time"], message["level"], message["full_module_name"], message["message"], str(message["levelno"])) def add_entry(self, date, level, module, message, levelno): """Adds the given fields to a new row in the log table It is called by message() when a log message is received""" items = [QStandardItem(date), QStandardItem(level), QStandardItem(module), QStandardItem(message), QStandardItem(levelno)] for item in items: item.setEditable(False) self.table_model.appendRow(items) def slider_set_level(self, level): self.current_level_label.setText(self.log_levels[level]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format(self.level_colors[level])) self.set_level(level + 1) def set_level(self, level): """Sets the current level of the LogDialog. Level is based on the selection made in the levels_combo_box. It hides all messages with a lower level.""" self.level = level * 10 for i in range(self.table_model.rowCount()): if int(str(self.table_model.item(i, self.level_num_column).text())) < self.level: self.table_view.setRowHidden(i, True) else: self.table_view.setRowHidden(i, False)
class FlightPlanBaseDlg(QDialog): def __init__(self, parent): QDialog.__init__(self, parent) palette = QPalette(); brush = QBrush(QColor(255, 255, 255, 255)); brush.setStyle(Qt.SolidPattern); palette.setBrush(QPalette.Active, QPalette.Base, brush); palette.setBrush(QPalette.Active, QPalette.Window, brush); palette.setBrush(QPalette.Inactive, QPalette.Base, brush); palette.setBrush(QPalette.Inactive, QPalette.Window, brush); palette.setBrush(QPalette.Disabled, QPalette.Base, brush); palette.setBrush(QPalette.Disabled, QPalette.Window, brush); self.setPalette(palette); self.ui = Ui_FlightPlannerBase() self.ui.setupUi(self) self.newDlgExisting = False self.chbHideCloseInObst = QCheckBox(self.ui.grbResult) font = QFont() font.setBold(False) font.setWeight(50) self.chbHideCloseInObst.setFont(font) self.chbHideCloseInObst.setObjectName("chbHideCloseInObst") self.ui.vlResultGroup.addWidget(self.chbHideCloseInObst) self.chbHideCloseInObst.setText("Hide close-in obstacles") self.chbHideCloseInObst.setVisible(False) self.ui.tblHistory.setSelectionBehavior(1) # self.ui.tabCtrlGeneral.setTabsClosable(True) self.ui.btnUpdateQA.setVisible(False) self.ui.btnUpdateQA_2.setVisible(False) ''' combo boxes event ''' self.ui.cmbObstSurface.currentIndexChanged.connect(self.cmbObstSurfaceChanged) self.ui.cmbUnits.currentIndexChanged.connect(self.changeResultUnit) ''' buttons clicked connect ''' self.ui.btnClose.clicked.connect(self.reject) self.ui.btnClose_2.clicked.connect(self.reject) self.ui.btnHistoryClose.clicked.connect(self.reject) self.ui.btnConstruct.clicked.connect(self.btnConstruct_Click) self.ui.btnEvaluate.clicked.connect(self.btnEvaluate_Click) self.ui.btnOpenData.clicked.connect(self.openData) self.ui.btnSaveData.clicked.connect(self.saveData) self.ui.btnPDTCheck.clicked.connect(self.btnPDTCheck_Click) self.ui.btnExportResult.clicked.connect(self.exportResult) self.ui.tblHistory.clicked.connect(self.tblHistory_Click) self.ui.btnUpdateQA.clicked.connect(self.btnUpdateQA_Click) self.ui.btnUpdateQA_2.clicked.connect(self.btnUpdateQA_2_Click) self.ui.btnCriticalLocate.clicked.connect(self.criticalLocate) self.connect(self.ui.tblObstacles, SIGNAL("tableViewObstacleMouseReleaseEvent_rightButton"), self.tableViewObstacleMouseTeleaseEvent_rightButton) self.connect(self.ui.tblObstacles, SIGNAL("pressedEvent"), self.tblObstacles_pressed) ''' properties ''' self.parametersPanel = None self.obstaclesModel = None self.surfaceType = "" self.surfaceSubGroupNames = [] self.uiStateInit() self.obstacleTableInit() self.newDlgExisting = True self.resultColumnNames = [] self.stdItemModelHistory = QStandardItemModel() # self.stdItemModelHistory. self.ui.tblHistory.setModel(self.stdItemModelHistory) icon = QIcon() icon.addPixmap(QPixmap("Resource/btnImage/dlgIcon.png"), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.resultLayerList = [] self.symbolLayers = [] self.selectedObstacleMoselIndex = None self.changedCriticalObstacleValue = [] def tblObstacles_pressed(self, modelIndex): self.selectedObstacleMoselIndex = modelIndex def tableViewObstacleMouseTeleaseEvent_rightButton(self, e): if self.obstaclesModel == None: return featID = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexObjectId)).toString() layerID = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexLayerId)).toString() name = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexName)).toString() xValue = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexX)).toString() yValue = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexY)).toString() altitudeMValue = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexAltM)).toString() surfaceName = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexSurface)).toString() ocaMValue = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexOcaM)).toString() # ocaMValue = self.obstaclesModel.data(self.obstaclesModel.index(self.selectedObstacleMoselIndex.row(), self.obstaclesModel.IndexOcaM)).toString() obstacle = Obstacle(name, Point3D(float(xValue), float(yValue), float(altitudeMValue)), layerID, featID, None, 0.0, self.obstaclesModel.MocMultiplier, 0.0) self.changedCriticalObstacleValue = {"Obstacle": obstacle, "SurfaceName": surfaceName, "OcaM": float(ocaMValue) if ocaMValue != "" else None} menu = QMenu() actionSetCriticalObst = QgisHelper.createAction(menu, "Set Most Critical Obstacles", self.menuSetCriticalObstClick) menu.addAction( actionSetCriticalObst ) menu.exec_( self.ui.tblObstacles.mapToGlobal(e.pos() )) def menuSetCriticalObstClick(self): pass # OasObstacles.resultCriticalObst.Obstacle = self.changedCriticalObstacleValue["Obstacle"] # OasObstacles.resultCriticalObst.Surface = self.changedCriticalObstacleValue["SurfaceName"] # OasObstacles.resultCriticalObst.Assigned = True # ocaMValue = self.changedCriticalObstacleValue["OcaM"] # # OasObstacles.resultOCA = Altitude(float(ocaMValue) if ocaMValue != "" else None) # if OasObstacles.resultOCA == None: # OasObstacles.resultOCH = None # else: # OasObstacles.resultOCH = OasObstacles.resultOCA - self.ui.pnlThr.Altitude() # # point3d = self.ui.pnlThr.Point3d # num = Unit.ConvertDegToRad(float(self.ui.txtTrack.Value)) # num1 = self.method_40() # zC = OasObstacles.constants.ZC / OasObstacles.constants.ZA # point3d1 = MathHelper.distanceBearingPoint(point3d, num, zC) # metres2 = OasObstacles.resultCriticalObst.method_2(point3d).Metres # z = metres2 - point3d.z() # num3 = math.tan(Unit.ConvertDegToRad(num1)) # num4 = z / num3 # OasObstacles.resultSocPosition = MathHelper.distanceBearingPoint(point3d1, num + 3.14159265358979, num4).smethod_167(0) # if (num4 > zC): # OasObstacles.resultSocText = Messages.X_BEFORE_THRESHOLD % (num4 - zC) # else: # OasObstacles.resultSocText = Messages.X_PAST_THRESHOLD % (zC - num4) # self.setCriticalObstacle() def criticalLocate(self): point = None try: point = QgsPoint(float(self.ui.txtCriticalX.text()), float(self.ui.txtCriticalY.text())) except: return if define._units == QGis.Meters: extent = QgsRectangle(point.x() - 350, point.y() - 350, point.x() + 350, point.y() + 350) else: extent = QgsRectangle(point.x() - 0.005, point.y() - 0.005, point.x() + 0.005, point.y() + 0.005) if extent is None: return QgisHelper.zoomExtent(point, extent, 2) def trackRadialPanelSetEnabled(self): positionPanels = self.findChildren(PositionPanel) if len(positionPanels) > 0: flag = False for pnl in positionPanels: if pnl.IsValid(): flag = True break trPanels = self.findChildren(TrackRadialBoxPanel) if len(trPanels) > 0: for pnl in trPanels: pnl.Enabled = flag def setDataInHistoryModel(self, dataList, newFlag = False): # dataList is list of list of tuple with name and data # example # dataList = [ list of name, list of data ] # dataList = [["lat", "lon"], ["59", "17"]] if newFlag: self.stdItemModelHistory.setHorizontalHeaderLabels(dataList[0][0]) for i in range(len(dataList)): for j in range(len(dataList[i][1])): item = QStandardItem(dataList[i][1][j]) item.setEditable(False) self.stdItemModelHistory.setItem(i, j, item) return if len(dataList) > 0: rowcount = self.stdItemModelHistory.rowCount() if self.stdItemModelHistory.rowCount() > 0: for i in range(len(dataList[1])): item = QStandardItem(dataList[1][i]) item.setEditable(False) self.stdItemModelHistory.setItem(rowcount, i, item) pass else: self.stdItemModelHistory.setHorizontalHeaderLabels(dataList[0]) for i in range(len(dataList[1])): item = QStandardItem(dataList[1][i]) item.setEditable(False) self.stdItemModelHistory.setItem(0, i, item) def btnPDTCheck_Click(self): pass def cmbObstSurfaceChanged(self): if self.obstaclesModel != None: if self.ui.cmbObstSurface.currentIndex() == 0 and self.ui.cmbObstSurface.currentText() == "All": self.obstaclesModel.setFilterFixedString("") else: self.obstaclesModel.setFilterFixedString(self.ui.cmbObstSurface.currentText()) def obstacleTableInit(self): self.ui.tblObstacles.setSelectionBehavior(QAbstractItemView.SelectRows) self.ui.tblObstacles.setSortingEnabled(True) def uiStateInit(self): self.ui.cmbUnits.addItems([Captions.METRES, Captions.FEET]) self.ui.cmbUnits.setCurrentIndex(1) self.ui.cmbUnits.currentIndexChanged.connect(self.changeResultUnit) pass def tblHistory_Click(self, modelIndex): pass def btnConstruct_Click(self): # qgsLayerTreeView = define._mLayerTreeView # groupName = self.surfaceType # layerTreeModel = qgsLayerTreeView.layerTreeModel() # layerTreeGroup = layerTreeModel.rootGroup() # rowCount = layerTreeModel.rowCount() # groupExisting = False # if rowCount > 0: # for i in range(rowCount): # qgsLayerTreeNode = layerTreeModel.index2node(layerTreeModel.index(i, 0)) # if qgsLayerTreeNode.nodeType() == 0: # qgsLayerTreeNode._class_ = QgsLayerTreeGroup # if isinstance(qgsLayerTreeNode, QgsLayerTreeGroup) and qgsLayerTreeNode.name() == groupName: # groupExisting = True # # if groupExisting: # if len(self.resultLayerList) > 0: # QgisHelper.removeFromCanvas(define._canvas, self.resultLayerList) # self.resultLayerList = [] # else: # QMessageBox.warning(self, "Warning", "Please remove \"" + self.surfaceType + "\" layer group from LayerTreeView.") # return False self.resultLayerList = [] return True def btnUpdateQA_Click(self): pass def btnUpdateQA_2_Click(self): pass def btnEvaluate_Click(self): try: if self.obstaclesModel == None: self.initObstaclesModel() if self.obstaclesModel == None: return surfaceLayers = QgisHelper.getSurfaceLayers(self.surfaceType, self.surfaceSubGroupNames) self.initObstaclesModel() self.obstaclesModel.loadObstacles(surfaceLayers) self.obstaclesModel.setLocateBtn(self.ui.btnLocate) self.ui.tblObstacles.setModel(self.obstaclesModel) self.obstaclesModel.setTableView(self.ui.tblObstacles) self.obstaclesModel.setHiddenColumns(self.ui.tblObstacles) self.ui.tabCtrlGeneral.setCurrentIndex(1) if self.ui.cmbObstSurface.isVisible(): self.ui.cmbObstSurface.clear() self.initSurfaceCombo() self.ui.cmbObstSurface.setCurrentIndex(0) self.ui.btnExportResult.setEnabled(True) self.setResultPanel() except UserWarning as e: QMessageBox.warning(self, "Information", e.message) def initParametersPan(self): parametersPanelWidget = QWidget(self) # self.parametersPanel = uiObject if self.parametersPanel != None: self.parametersPanel.setupUi(parametersPanelWidget) self.ui.vlScrollWidget.addWidget(parametersPanelWidget) lstTextControls = self.ui.grbGeneral.findChildren(QLineEdit) for ctrl in lstTextControls: ctrl.textChanged.connect(self.initResultPanel) lstComboControls = self.ui.grbGeneral.findChildren(QComboBox) for ctrl in lstComboControls: ctrl.currentIndexChanged.connect(self.initResultPanel) # lstTextControls = self.findChildren(QLineEdit) # for ctrl in lstTextControls: # ctrl.setMinimumWidth(100) # ctrl.setMaximumWidth(100) # lstComboControls = self.findChildren(QComboBox) # for ctrl in lstComboControls: # ctrl.setMinimumWidth(100) # ctrl.setMaximumWidth(100) # newWidth = int(define._appWidth / float(1280) * parametersPanelWidget.width()) # newHeight = int(define._appHeight / float(800) * parametersPanelWidget.height()) # if newWidth > define._appWidth: # newWidth -= 50 # if newHeight > define._appHeight: # newHeight -= 50 # parametersPanelWidget.resize(newWidth, newHeight) def initResultPanel(self): if self.obstaclesModel != None and self.ui.btnEvaluate.isEnabled(): self.obstaclesModel.clear() lstTextControls = self.ui.grbResult.findChildren(QLineEdit) for ctrl in lstTextControls: if ctrl.objectName() == "txtOCH" or ctrl.objectName() == "txtOCA": continue ctrl.setText("") self.ui.btnExportResult.setDisabled(True) # self.ui.btnEvaluate.setEnabled(False) def initObstaclesModel(self): pass def initSurfaceCombo(self): pass def setResultPanel(self): pass def saveData(self): try: filePathDir = QFileDialog.getSaveFileName(self, "Save Input Data",QCoreApplication.applicationDirPath (),"Xml Files(*.xml)") if filePathDir == "": return DataHelper.saveInputParameters(filePathDir, self) # contents = None # with open(filePathDir, 'rb', 0) as tempFile: # contents = tempFile.read() # tempFile.flush() # tempFile.close() # bytes = FasDataBlockFile.CRC_Calculation(contents) # string_0 = QString(filePathDir) # path = string_0.left(string_0.length() - 3) + "crc" # fileStream = open(path, 'wb') # fileStream.write(bytes) # fileStream.close() return filePathDir except UserWarning as e: QMessageBox.warning(self, "Error", e.message) def openData(self): try: filePathDir = QFileDialog.getOpenFileName(self, "Open Input Data",QCoreApplication.applicationDirPath (),"Xml Files(*.xml)") if filePathDir == "": return layers = define._canvas.layers() if layers != None and len(layers) > 0: for layer in layers: if layer.name() == "Symbols": self.currentLayer = layer try: self.initAerodromeAndRwyCmb() except: pass try: self.initBasedOnCmb() except: pass break # contents = None # with open(filePathDir, 'rb', 0) as tempFile: # contents = tempFile.read() # tempFile.close() # bytes = FasDataBlockFile.CRC_Calculation(contents) # # string_0 = QString(filePathDir) # crcFileDir = string_0.left(string_0.length() - 3) + "crc" # crcFileContents = None # with open(crcFileDir, 'rb', 0) as tempFileCrc: # crcFileContents = tempFileCrc.read() # tempFileCrc.close() # if bytes != crcFileContents: # QMessageBox.warning(self, "Error", "Input file has been changed by outside.") # return DataHelper.loadInputParameters(filePathDir, self) return filePathDir except UserWarning as e: QMessageBox.warning(self, "Error", e.message) def exportResult(self): dlg = ExportDlg(self) dlg.ui.txtHeading.setText(self.surfaceType + "_Export") columnNames = [] if self.obstaclesModel != None: columnNames = self.obstaclesModel.fixedColumnLabels self.stModel = QStandardItemModel() for i in range(len(columnNames)): stItem = QStandardItem(columnNames[i]) stItem.setCheckable(True) checkFlag = True for hideColName in self.obstaclesModel.hideColumnLabels: if columnNames[i] == hideColName: checkFlag = False break if checkFlag: stItem.setCheckState(Qt.Checked) else: stItem.setCheckState(Qt.Unchecked) self.stModel.setItem(i, 0, stItem) if len(columnNames) <= 0: return dlg.ui.listColumns.setModel(self.stModel) result = dlg.exec_() return (result, dlg.resultHideColumnIndexs) def changeResultUnit(self): pass def method_27(self, qarecord_0): pass # QA.smethod_2(qarecord_0); # self.method_20(Messages.QA_UPDATED);
class Browser(QWidget): entrytype = type("EntryType", (object,), dict((v,k) for k,v in enumerate( ["directory", "playlist", "mediafile", "url"] ))) col = type("BrowserColumns", (object,), dict((v,k) for k,v in enumerate( ["name", "last_modified", "entrytype", "uri"] ))) @staticmethod def columns(): return len(dict((k,v) for k,v in Browser.col.__dict__.items() if not k.startswith("__"))) def __init__(self,app): super(Browser,self).__init__() self.mpd = app.mpd self.ih = app.imagehelper self.model = QStandardItemModel(0,self.columns(),self) self.initGUI() self.initActions() def initGUI(self): self.setWindowTitle(QApplication.applicationName()) layout = QVBoxLayout() headerlayout = QHBoxLayout() homeBtn = QToolButton() homeBtn.setIcon(self.ih.homeButton) homeBtn.setFixedSize(64,64) homeBtn.clicked.connect(self.home) headerlayout.addWidget(homeBtn) label = QLabel("<b>Location</b>") label.setMargin(10) label.setFixedSize(label.sizeHint()) headerlayout.addWidget(label) self.currentLocation = ClickableLabel("") self.currentLocation.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.currentLocation.setWordWrap(True) self.currentLocation.setFixedSize(400,64) self.currentLocation.clicked.connect(self.back) headerlayout.addWidget(self.currentLocation) headerlayout.addStretch() layout.addLayout(headerlayout) self.view = QListView() self.view.setSelectionMode( QAbstractItemView.SingleSelection) self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.view.setContextMenuPolicy(Qt.CustomContextMenu) self.view.customContextMenuRequested.connect(self.contextMenu) self.view.setModel(self.model) self.view.setModelColumn(0) #self.view.doubleClicked.connect(self.doubleClicked) self.view.activated.connect(self.activated) layout.addWidget(self.view) self.setLayout(layout) def initActions(self): self.actionAdd = QAction("Add", self) self.actionAddPlay = QAction("Add and Play", self) self.actionInsert = QAction("Insert", self) self.actionReplace = QAction("Replace", self) self.actionReplacePlay = QAction("Replace and Play", self) self.actionUpdate = QAction("Update", self) self.actionUpdateAll = QAction("Update all", self) # playlist actions self.actionPlsRename = QAction("Rename", self) self.actionPlsDelete = QAction("Delete", self) def contextMenu(self,pos): if self.model.rowCount() == 0: return mi = self.view.selectionModel().currentIndex() if not mi.isValid(): return uri = self.model.item(mi.row(),self.col.uri).text() entrytype = int(self.model.item(mi.row(),self.col.entrytype).text()) addfunc = None if entrytype != self.entrytype.playlist: addfunc = self.mpd.add else: addfunc = self.mpd.load popup = QMenu() popup.addAction(self.actionAdd) popup.addAction(self.actionAddPlay) if entrytype == self.entrytype.mediafile or \ entrytype == self.entrytype.url: popup.addAction(self.actionInsert) popup.addAction(self.actionReplace) popup.addAction(self.actionReplacePlay) if entrytype == self.entrytype.playlist: popup.addAction(self.actionPlsRename) popup.addAction(self.actionPlsDelete) else: popup.addAction(self.actionUpdate) popup.addAction(self.actionUpdateAll) action = popup.exec_(self.mapToGlobal(pos)) status = self.mpd.status() if action == self.actionAdd: addfunc(uri) elif action == self.actionAddPlay: addfunc(uri) self.mpd.play(int(status['playlistlength'])) elif action == self.actionInsert: song = int(status.get('song',-1))+1 self.mpd.addid(uri,song) elif action == self.actionReplace: self.mpd.clear() addfunc(uri) elif action == self.actionReplacePlay: self.mpd.clear() addfunc(uri) self.mpd.play() elif action == self.actionUpdate: ans = QMessageBox.question( self, "Update", "Trigger update for '%s'?" % uri, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ans == QMessageBox.Yes: self.mpd.update(uri) elif action == self.actionUpdateAll: self.mpd.update() elif action == self.actionPlsRename: ans, ok = QInputDialog.getText( self, "Rename playlist", "Rename playlist '%s':" % uri) plsname = unicode(ans) if ok and plsname != uri: for pls in self.mpd.listplaylists(): if pls['playlist'] == plsname: overwrite = QMessageBox.question( self, "Rename playlist", "Playlist exists, overwrite?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if overwrite == QMessageBox.Yes: self.mpd.rm(plsname) self.mpd.rename(uri,plsname) break else: self.mpd.rename(uri, plsname) self.home() elif action == self.actionPlsDelete: ans = QMessageBox.question( self, "Delete '%s'" % uri, "Are you sure?" % uri, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ans == QMessageBox.Yes: self.mpd.rm(uri) self.home() def showDirectory(self,uri): try: info = self.mpd.lsinfo(uri) except MPDError, e: print e return rows = [] for entry in [ d for d in info if not d.has_key('playlist')]: row = self.createRow(entry) if not row: continue rows += [row] for entry in sorted([ d for d in info if d.has_key('playlist')], key=operator.itemgetter('playlist')): row = self.createRow(entry) if not row: continue rows += [row] self.currentLocation.setText(uri) self.updateModel(rows)
class Formation(QMainWindow, Ui_Formation): """ Class documentation goes here. """ #signal fermeture_reouverture = pyqtSignal() maj = pyqtSignal() def __init__(self, engine, gui_parent, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super().__init__(parent) self.setupUi(self) self.setWindowTitle("Enregistrement d'une formation") self.engine = engine self.dateEdit.setDate(pendulum.now('Europe/Paris')) self.cmr_bdd = Bdd_Cmr(self.engine) gen_cmr = self.cmr_bdd.recup_cmr_en_activite() self.remplir_tableau_cmr(next(gen_cmr)) # self.threadpool = QThreadPool() self.gui_parent = gui_parent ####Threads self.thread_finish = False # self.affectation_lancement_threads() init_domaine = Insertion_Domaine(self.engine) areas = init_domaine.recuperation_domaine() # print(areas) self.model = QStandardItemModel((len(areas) + 1), 1) # 5 rows, 1 col firstItem = QStandardItem("---- Select domaine(s) ----") firstItem.setBackground(QBrush(QColor(200, 200, 200))) firstItem.setSelectable(False) self.model.setItem(0, 0, firstItem) for i, area in enumerate(areas): item = QStandardItem(area) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(Qt.Unchecked, Qt.CheckStateRole) self.model.setItem(i + 1, 0, item) self.comboBox_domaine.setModel(self.model) self.gui_parent.formation_a_modifier.connect( self.reaffectation_formation) # # def affectation_lancement_threads(self): # """"met en place les threads et les lance""" # bdd_thread = Gestion_BDD_Thread(self.cmr_bdd ) # bdd_thread.signals.signalData_dispo.connect(self.remplir_tableau_cmr) # self.threadpool.start(bdd_thread) ### bdd_thread.run() # # self.thread_combobox = Gestion_Combobox_domaine_Thread(self.engine) # self.thread_combobox.signals.signalmodel_dispo.connect(self.affectation_model_combobox_domaine) ## self.thread_combobox.finished.connect(self.danslemille) # self.threadpool.start(self.thread_combobox) # # print(self.thread_combobox) ## self.thread_combobox.run() # # @pyqtSlot(QStandardItemModel) # def affectation_model_combobox_domaine(self, model): # """permet de recevoir le model créé et affecte au combobox dans le thread specifique""" # print("jy suis") # mutex = QMutex() # mutex.lock() # self.model = model # self.comboBox_domaine.setModel(self.model) # # self.thread_finish = True # mutex.unlock() # print(self.thread_finish) @pyqtSlot(list) def remplir_tableau_cmr(self, gen_list_cmr): self.tableWidget.setRowCount(0) for cmr in reversed(gen_list_cmr): # print(cmr) self.tableWidget.insertRow(0) item_nom = QTableWidgetItem(cmr.NOM) item_prenom = QTableWidgetItem(cmr.PRENOM) self.tableWidget.setItem(0, 0, item_nom) self.tableWidget.setItem(0, 1, item_prenom) self.tableWidget.setCellWidget(0, 2, QComboBox()) self.tableWidget.cellWidget(0, 2).addItems( ["*", "Acquise", "À améliorer", "Non acquise"]) self.tableWidget.setCellWidget(0, 3, QComboBox()) self.tableWidget.cellWidget(0, 3).addItems( [str(x) for x in range(21)]) self.tableWidget.setCellWidget(0, 4, QTextEdit()) self.tableWidget.setCellWidget(0, 5, QCheckBox()) @pyqtSlot() def on_pushButton_enregistrer_clicked(self): """ Slot documentation goes here. """ nom_formation = self.lineEdit_nom_formation.text() if nom_formation: date = self.dateEdit.date().toString("dd-MM-yyyy") type_formation = self.comboBox_type_formation.currentText() # domaine = self.comboBox_domaine.currentText() domaine = [] for ligne in range(self.model.rowCount()): if self.model.item(ligne, 0).checkState() == Qt.Checked: domaine.append(self.model.item(ligne, 0).text()) plan = self.textEdit_plan_formation.toPlainText() nbr_ligne = self.tableWidget.rowCount() sauvegarde_dico = [] for ligne in range(nbr_ligne): if self.tableWidget.cellWidget(ligne, 5).isChecked(): nom = self.tableWidget.item(ligne, 0).text() prenom = self.tableWidget.item(ligne, 1).text() gen_id = self.cmr_bdd.recup_id_cmr(nom, prenom) try: resultat = self.tableWidget.cellWidget( ligne, 2).currentText() except: resultat = None try: note = self.tableWidget.cellWidget(ligne, 3).currentText() except: note = None try: remarque = self.tableWidget.item(ligne, 4).text() except: remarque = None dico = { "nom": nom, "prenom": prenom, "id": gen_id, "resultat": resultat, "note": note, "remarque": remarque } # print(dico) sauvegarde_dico.append(json.dumps(dico)) sauvegarde = { "nom_formation": nom_formation, "date": date, "type_formation": type_formation, "domaine": domaine, "plan": plan, "participants": sauvegarde_dico } # print(sauvegarde) if self.windowTitle() == "Enregistrement d'une formation": self.cmr_bdd.insertion_formation(sauvegarde) self.close() self.fermeture_reouverture.emit() else: #on est dans une modification self.cmr_bdd.modif_formation(self.id_formation_a_modif, sauvegarde) self.close() self.maj.emit() @pyqtSlot(object) def reaffectation_formation(self, formation): """fct qui reaffecte les donnees recues par le signal""" self.setWindowTitle("Modification d'une formation") # print(formation) self.id_formation_a_modif = formation.ID # print(formation.ID) self.lineEdit_nom_formation.setText(formation.NOM_FORMATION) self.dateEdit.setDate(formation.DATE_FORMATION) index = self.comboBox_type_formation.findText(formation.TYPE_FORMATION, Qt.MatchExactly) if index: self.comboBox_type_formation.setCurrentIndex(index) #gestion des domaines : for domaine in formation.DOMAINE: for ligne in range(self.model.rowCount()): # print(f"ligne {ligne}") if self.model.item(ligne, 0).text() == domaine: self.model.item(ligne, 0).setData(Qt.Checked, Qt.CheckStateRole) self.textEdit_plan_formation.setText(formation.PLAN) for participant in formation.LIST_PARTICIPANTS: nom = json.loads(participant)["nom"] prenom = json.loads(participant)["prenom"] # id = json.loads(participant)["id"] resultat = json.loads(participant)["resultat"] note = json.loads(participant)["note"] remarque = json.loads(participant)["remarque"] for ligne in range(self.tableWidget.rowCount()): if self.tableWidget.item( ligne, 0).text() == nom and self.tableWidget.item( ligne, 1).text() == prenom: index = self.tableWidget.cellWidget(ligne, 2).findText( resultat, Qt.MatchExactly) if index != -1: self.tableWidget.cellWidget(ligne, 2).setCurrentIndex(index) index = self.tableWidget.cellWidget(ligne, 3).findText( note, Qt.MatchExactly) if index != -1: self.tableWidget.cellWidget(ligne, 3).setCurrentIndex(index) self.tableWidget.cellWidget(ligne, 4).setText(remarque) self.tableWidget.cellWidget(ligne, 5).setChecked(True)
class OrderSelectorModel(QObject): """""" #---------------------------------------------------------------------- def __init__(self, full_string_list, init_selected_string_list=None, permanently_selected_string_list=None): """Constructor""" QObject.__init__(self) self.output = [] if not self.hasNoDuplicateStrings(full_string_list): raise ValueError('Duplicate strings detected in full string list.') else: self.full_string_list = full_string_list[:] if init_selected_string_list is not None: if not self.allStringsInList1FoundInList2( init_selected_string_list, self.full_string_list): raise ValueError( 'Some of the strings in initially selected string list are not in full string list.' ) else: init_selected_string_list = [] if permanently_selected_string_list is not None: if not self.allStringsInList1FoundInList2( permanently_selected_string_list, init_selected_string_list): raise ValueError( 'Some of the strings in permanently selected string list are not in initially selected string list.' ) else: permanently_selected_string_list = [] self.permanently_selected_string_list = permanently_selected_string_list[:] self.model_Selected = QStandardItemModel() self.model_NotSelected = QStandardItemModel() Selected_item_list = [None for s in init_selected_string_list] NotSelected_item_list = [] for s in self.full_string_list: item = QStandardItem(s) try: Selected_item_list[init_selected_string_list.index(s)] = item except: NotSelected_item_list.append(item) for item in NotSelected_item_list: self.model_NotSelected.appendRow(item) for item in Selected_item_list: self.model_Selected.appendRow(item) #---------------------------------------------------------------------- def getSelectedList(self): """""" selectedList = [] for i in range(self.model_Selected.rowCount()): selectedList.append(self.model_Selected.item(i, 0).text()) return selectedList #---------------------------------------------------------------------- def hasNoDuplicateStrings(self, full_string_list): """""" str_list = full_string_list str_set = set(full_string_list) if len(str_list) == len(str_set): return True else: return False #---------------------------------------------------------------------- def allStringsInList1FoundInList2(self, str_list_1, str_list_2): """""" stringsNotFound = [s for s in str_list_1 if s not in str_list_2] if stringsNotFound != []: return False else: return True
class ListPairTableView(QTableView): """ 2-column table view that enables pairing of list data through combo boxes. """ def __init__(self, parent=None): QTableView.__init__(self, parent) self.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.SelectedClicked) self.setSelectionBehavior(QAbstractItemView.SelectRows) self._pair_model = QStandardItemModel(1, 2, self) self._pair_model.dataChanged.connect(self._on_pair_data_changed) self.setModel(self._pair_model) self.horizontalHeader().setResizeMode(QHeaderView.Stretch) self._combo_delegate = PairComboBoxDelegate(self) self.setItemDelegate(self._combo_delegate) def set_header_labels(self, labels): """ Set the table's header labels using labels. :param labels: Header labels. :type labels: list """ if len(labels) < 2: return lbls = [] for i in range(2): lbls.append(labels[i]) self._pair_model.setHorizontalHeaderLabels(lbls) def clear_view(self): """ Clears all row pairings in the view. """ rows = self._pair_model.rowCount() self._pair_model.removeRows(0, rows) #Insert blank row self.append_row() def append_row(self): """ Add a blank row after the last item in the view. """ items = [QStandardItem(), QStandardItem()] self._pair_model.appendRow(items) def set_combo_selection(self, selection, empty_item=True): """ Set combo selection for both columns. Any existing rows will be removed from the view. :param selection: A list containing two sub-lists for each column that correspond to the selection list for the combobox in each column. :type selection: list :param empty_item: True to insert an empty first item in each of the column comboboxes. :type empty_item: bool """ self._combo_delegate.set_items_pair(selection, empty_item) self.clear_view() def _on_pair_data_changed(self, old_index, new_index): """ This slot asserts whether selections in both columns in a row have been specified. If true, then automatically adds a new empty row for additional entries; If false, then the empty is removed from the view. :param old_index: Model index :type old_index: QModelIndex :param new_index: Model index :type new_index: QModelIndex """ row_state = self.row_data_state(new_index.row()) row_data = self.row_data(new_index.row()) if row_state == 0: self._pair_model.removeRows(new_index.row(), 1) if self._pair_model.rowCount() == 0: self.append_row() elif row_state == 2: if not self.is_last_row_empty(): self.append_row() def is_last_row_empty(self): """ :return: True if the last row in the view does not contain any data, False if one or both columns contains data. :rtype: bool """ last_row_idx = self._pair_model.rowCount() - 1 last_row_state = self.row_data_state(last_row_idx) if last_row_state == 0: return True else: return False def row_data_state(self, row_index): """ :param row_index: Row position :type row_index: int :return: 0 if data for each of the columns is empty. 1 if one column contains data and the other is empty. 2 if both columns contain data. :rtype: int """ col_0_val, col_1_val = self.row_data(row_index) if col_0_val is None and col_1_val is None: return 0 elif self._is_empty(col_0_val) and not self._is_empty(col_1_val): return 1 elif not self._is_empty(col_0_val) and self._is_empty(col_1_val): return 1 elif self._is_empty(col_0_val) and self._is_empty(col_1_val): return 0 elif not self._is_empty(col_0_val) and not self._is_empty(col_1_val): return 2 def _is_empty(self, val): if val is None: return True else: if (isinstance(val, str) or isinstance(val, unicode)) and not val: return True return False def row_data(self, row_index): """ :param row_index: Row position :type row_index: int :return: Data in both first and second columns for the specified row. :rtype: tuple """ if row_index >= 0: idx_col_0 = self._pair_model.index(row_index, 0) idx_col_1 = self._pair_model.index(row_index, 1) val_0 = self._pair_model.data(idx_col_0) val_1 = self._pair_model.data(idx_col_1) return val_0, val_1 else: return None, None def column_pairings(self): """ :return: Collection of column matchings specified as specified by the user. :rtype: dict """ col_pairings = {} for row_idx in range(self._pair_model.rowCount()): if self.row_data_state(row_idx) != 0: col_val_0, col_val_1 = self.row_data(row_idx) col_pairings[col_val_0] = col_val_1 return col_pairings
class ListWidget(EditorWidget): widgettype = 'List' def __init__(self, *args): super(ListWidget, self).__init__(*args) self.listmodel = QStandardItemModel() self._bindvalue = None def createWidget(self, parent): return QComboBox(parent) def _buildfromlist(self, widget, listconfig): items = listconfig['items'] for item in items: parts = item.split(';') data = parts[0] try: desc = parts[1] except IndexError: desc = data try: path = parts[2] icon = QIcon(path) except: icon = QIcon() item = QStandardItem(desc) item.setData(data, Qt.UserRole) item.setIcon(icon) self.listmodel.appendRow(item) def _buildfromlayer(self, widget, layerconfig): layername = layerconfig['layer'] keyfield = layerconfig['key'] valuefield = layerconfig['value'] filterexp = layerconfig.get('filter', None) try: layer = QgsMapLayerRegistry.instance().mapLayersByName(layername)[0] except IndexError: roam.utils.warning("Can't find layer {} in project".format(layername)) return keyfieldindex = layer.fieldNameIndex(keyfield) valuefieldindex = layer.fieldNameIndex(valuefield) if keyfieldindex == -1 or valuefieldindex == -1: roam.utils.warning("Can't find key or value column") return if self.allownulls: item = QStandardItem('(no selection)') item.setData(None, Qt.UserRole) self.listmodel.appendRow(item) attributes = {keyfieldindex, valuefieldindex} iconfieldindex = layer.fieldNameIndex('icon') if iconfieldindex > -1: attributes.add(iconfieldindex) if not filterexp and valuefieldindex == keyfieldindex and iconfieldindex == -1: values = layer.uniqueValues(keyfieldindex) for value in values: value = nullconvert(value) item = QStandardItem(value) item.setData(value, Qt.UserRole) self.listmodel.appendRow(item) return flags = QgsFeatureRequest.NoGeometry expression = None if filterexp: expression = QgsExpression(filterexp) expression.prepare(layer.pendingFields()) if expression.hasParserError(): roam.utils.warning("Expression has parser error: {}".format(expression.parserErrorString())) return if expression.needsGeometry(): flags = QgsFeatureRequest.NoFlags for field in expression.referencedColumns(): index = layer.fieldNameIndex(field) attributes.add(index) request = QgsFeatureRequest().setFlags(flags).setSubsetOfAttributes(list(attributes)) for feature in layer.getFeatures(request): if expression and not expression.evaluate(feature): continue keyvalue = nullconvert(feature[keyfieldindex]) valuvalue = nullconvert(feature[valuefield]) try: path = feature[iconfieldindex] icon = QIcon(path) except KeyError: icon = QIcon() item = QStandardItem(unicode(keyvalue)) item.setData(unicode(valuvalue), Qt.UserRole) item.setIcon(icon) self.listmodel.appendRow(item) def initWidget(self, widget): if widget.isEditable(): widget.editTextChanged.connect(self.emitvaluechanged) widget.currentIndexChanged.connect(self.emitvaluechanged) widget.setModel(self.listmodel) widget.showPopup = self.showpopup widget.setIconSize(QSize(24,24)) widget.setStyleSheet("QComboBox::drop-down {border-width: 0px;} QComboBox::down-arrow {image: url(noimg); border-width: 0px;}") def showpopup(self): if self.listmodel.rowCount() == 0: return self.largewidgetrequest.emit(BigListWidget, self.widget.currentIndex(), self._biglistitem, dict(model=self.listmodel, label=self.labeltext)) def updatefromconfig(self): super(ListWidget, self).updatefromconfig() self.listmodel.clear() if 'list' in self.config: listconfig = self.config['list'] self._buildfromlist(self.widget, listconfig) elif 'layer' in self.config: layerconfig = self.config['layer'] self._buildfromlayer(self.widget, layerconfig) super(ListWidget, self).endupdatefromconfig() @property def allownulls(self): return self.config.get('allownull', False) def validate(self, *args): if (not self.widget.currentText() == '' and not self.widget.currentText() == "(no selection)"): return True else: return False def _biglistitem(self, index): self.widget.setCurrentIndex(index.row()) def setvalue(self, value): self._bindvalue = value index = self.widget.findData(value) self.widget.setCurrentIndex(index) if index == -1 and self.widget.isEditable(): if value is None and not self.config['allownull']: return self.widget.addItem(str(value)) index = self.widget.count() - 1 self.widget.setCurrentIndex(index) def value(self): index = self.widget.currentIndex() value = self.widget.itemData(index) text = self.widget.currentText() if value is None and self.widget.isEditable() and not text == '(no selection)': return self.widget.currentText() return value
class MSClusteringController(MSDialogController): """ Class to Control the gui and the model for clustering """ POS_ADDUCTS=path.normcase('config/databases/POS_ADDUCTS.csv'), \ path.normcase('config/databases/POS_ADDUCTS_LOW_RES.csv') NEG_ADDUCTS=path.normcase('config/databases/NEG_ADDUCTS.csv'), \ path.normcase('config/databases/NEG_ADDUCTS_LOW_RES.csv') FRAGMENTS=path.normcase('config/databases/FRAGMENTS.csv'), \ path.normcase('config/databases/FRAGMENTS_LOW_RES.csv') def __init__(self, lspl, visu, creation): MSDialogController.__init__(self, lspl, visu, creation) self.polarity=1 #initialisation if not self.model: self.goodIdx = 0 else: self.goodIdx = 0 if self.model[0].kind == 'HighRes' else 1 self.populateTableViews(self.polarity) self.allAddsChecked = False self.allFragsChecked = False QObject.connect(self.view.posmode, SIGNAL('toggled(bool)'), self.updatePolarity) QObject.connect(self.view.checkAllAdds, SIGNAL('clicked()'), self.checkAdds) QObject.connect(self.view.checkAllFrags, SIGNAL('clicked()'), self.checkFrags) self.view.exec_() def getFragAddData(self, polarity=1): """parsing adducts and fragments files""" frags=self.readData(self.FRAGMENTS[self.goodIdx]) if not polarity: adds=self.readData(self.NEG_ADDUCTS[self.goodIdx]) elif polarity: adds=self.readData(self.POS_ADDUCTS[self.goodIdx]) return frags, adds def readData(self, file_): """read data from databases files""" def fragData(line, d): d[(s[0], s[1], str(1))]= False def addData(line, d): d[(s[0], s[-1].rstrip(), s[1])]= False routine=None if file_ in (self.POS_ADDUCTS+self.NEG_ADDUCTS): routine=addData elif file_ in self.FRAGMENTS: routine=fragData else: print ("Error reading adducts and fragments files") return res=OrderedDict() with open(file_) as f: for i in range (2): l=f.readline() while l!="": s=l.split(',') routine(l, res) l=f.readline() return res def checkAdds(self): for i in xrange(self.adductsModel.rowCount()): #data = self.adductsModel.item(i,0).text() item = self.adductsModel.item(i,0) if self.allAddsChecked: item.setCheckState(0) self.view.checkAllAdds.setText('Check All') else: item.setCheckState(2) self.view.checkAllAdds.setText('UnCheck All') self.allAddsChecked = not self.allAddsChecked def checkFrags(self): for i in xrange(self.fragsModel.rowCount()): #data = self.fragsModel.item(i,0).text() item = self.fragsModel.item(i,0) if self.allFragsChecked: item.setCheckState(0) self.view.checkAllFrags.setText('Check All') else: item.setCheckState(2) self.view.checkAllFrags.setText('UnCheck All') self.allFragsChecked = not self.allFragsChecked def populateTableViews(self, polarity): frags, adds = self.getFragAddData(polarity) self.adductsModel, self.fragsModel = QStandardItemModel(), QStandardItemModel() self.adductsModel.setHorizontalHeaderLabels(["Adducts(name, mass, nmol)"]) self.fragsModel.setHorizontalHeaderLabels(["Fragments(name, mass, nmol)"]) for i, adduct in enumerate(adds.keys()): item =QStandardItem(', '.join(map(str, adduct))) item.setCheckable(True) if adds[adduct]: item.setCheckState(2) else: item.setCheckState(0) self.adductsModel.setItem(i, 0, item) self.view.adductsTable.setModel(self.adductsModel) for i, frag in enumerate(frags.keys()): item = QStandardItem(', '.join(map(str, frag))) item.setCheckable(True) if frags[frag]: item.setCheckState(2) else: item.setCheckState(0) self.fragsModel.setItem(i, 0, item) self.view.fragTable.setModel(self.fragsModel) def getFragsAndAdductsToCheck(self): frags, adducts={}, {} for i in range(self.fragsModel.rowCount()): data = self.fragsModel.item(i,0).text() item = self.fragsModel.item(i,0) if item.checkState(): frags[tuple([str(x) for x in data.split(', ')])]= True else: frags[tuple([str(x) for x in data.split(', ')])]= False for i in range(self.adductsModel.rowCount()): data = self.adductsModel.item(i,0).text() item = self.adductsModel.item(i,0) if item.checkState(): adducts[tuple([str(x) for x in data.split(', ')])]= True else: adducts[tuple([str(x) for x in data.split(', ')])]= False checkMasses=OrderedDict() for frag in frags.keys(): if frags[frag]: checkMasses[(float(frag[1]), float(frag[2]))] = frag[0] for add in adducts.keys(): if adducts[add]: if self.polarity:#positive polarity checkMasses[(-float(add[1]), float(add[2]))] = add[0] elif not self.polarity:#negative polarity checkMasses[(float(add[1]), float(add[2]))] = add[0] return checkMasses def updatePolarity(self, boolean): self.polarity = 1 if boolean else 0#positive, negative self.populateTableViews(self.polarity) def getParameters(self): """classical getParameters (model) function""" self.parameters["rtError"] = self.view.lineEdit_2.value() self.parameters["clusterLength"] = self.view.lineEdit_3.value() self.parameters["idmsLength"] =tuple([float(x) for x in self.view.lineEdit_4.text().split('-')]) self.parameters["badPeaks"] = self.view.lineEdit_5.isChecked() #self.parameters["useCorr"] = self.view.check.isChecked() self.parameters["gap"]=self.view.spinBox.value() self.parameters["resolveConflicts"]=self.view.lineEdit_6.isChecked() self.parameters["frags"]=self.getFragsAndAdductsToCheck() def startTask(self): """ Main Function (model function) Clustering """ MSDialogController.startTask(self) #qApp.instance().view.showInStatusBar("Clustering Step...Please Wait..", 5000) self.task = MSClusterThread(self.sampleList, **self.parameters) QObject.connect(self.view, SIGNAL('destroyed(QObject *)'), self.task.begin) #self.connect(self.view, SIGNAL('destroyed(QObject *)'), self.setViewToNone) QObject.connect(self.task, SIGNAL("started()"),qApp.instance().view.to_determined_mode) QObject.connect(self.task, SIGNAL('update_pb'), qApp.instance().view.updateProgressBar) #QObject.connect(self.task, SIGNAL("finished()"),qApp.instance().view.to_determined_mode) QObject.connect(self.task, SIGNAL("finished()"), self.setModels) #print "about to close" self.view.close() #print "closed" #self.task.begin() def setModels(self):#, sampleList): """ closing function of the process """ qApp.instance().view.showInformationMessage("Clustering done", "Clustering Done succesfully !") qApp.instance().view.tabWidget.setCurrentIndex(2) def _initialize(self): """initialization of the parameters""" self.view.lineEdit_2.setValue(6.) self.view.lineEdit_3.setValue(6) self.view.lineEdit_4.setText("0-0") #self.view.lineEdit_5.setText("10.") self.view.decrOrder.setChecked(True) self.view.lineEdit_6.setChecked(True) self.view.spinBox.setValue(0)
class MultipleSelectTreeView(QListView): """ Custom QListView implementation that displays checkable items from a multiple select column type. """ def __init__(self, column, parent=None): """ Class constructor. :param column: Multiple select column object. :type column: MultipleSelectColumn :param parent: Parent widget for the control. :type parent: QWidget """ QListView.__init__(self, parent) #Disable editing of lookup values self.setEditTriggers(QAbstractItemView.NoEditTriggers) self.column = column self._item_model = QStandardItemModel(self) self._value_list = self.column.value_list #Stores lookup objects based on primary keys self._lookup_cache = {} self._initialize() self._association = self.column.association self._first_parent_col = self._association.first_reference_column.name self._second_parent_col = self._association.second_reference_column.name #Association model self._assoc_cls = entity_model(self._association) def reset_model(self): """ Resets the item model. """ self._item_model.clear() self._item_model.setColumnCount(2) def clear(self): """ Clears all items in the model. """ self._item_model.clear() @property def association(self): """ :return: Returns the association object corresponding to the column. :rtype: AssociationEntity """ return self._association @property def value_list(self): """ :return: Returns the ValueList object corresponding to the configured column object. :rtype: ValueList """ return self._value_list @property def item_model(self): """ :return: Returns the model corresponding to the checkable items. :rtype: QStandardItemModel """ return self._item_model def _add_item(self, id, value): """ Adds a row corresponding to id and corresponding value from a lookup table. :param id: Primary key of a lookup record. :type id: int :param value: Lookup value :type value: str """ value_item = QStandardItem(value) value_item.setCheckable(True) id_item = QStandardItem(str(id)) self._item_model.appendRow([value_item, id_item]) def _initialize(self): #Populate list with lookup items self.reset_model() #Add all lookup values in the value list table vl_cls = entity_model(self._value_list) if not vl_cls is None: vl_obj = vl_cls() res = vl_obj.queryObject().all() for r in res: self._lookup_cache[r.id] = r self._add_item(r.id, r.value) self.setModel(self._item_model) def clear_selection(self): """ Unchecks all items in the view. """ for i in range(self._item_model.rowCount()): value_item = self._item_model.item(i, 0) if value_item.checkState() == Qt.Checked: value_item.setCheckState(Qt.Unchecked) if value_item.rowCount() > 0: value_item.removeRow(0) def selection(self): """ :return: Returns a list of selected items. :rtype: list """ selection = [] for i in range(self._item_model.rowCount()): value_item = self._item_model.item(i, 0) if value_item.checkState() == Qt.Checked: id_item = self._item_model.item(i, 1) id = int(id_item.text()) #Get item from the lookup cache and append to selection if id in self._lookup_cache: lookup_rec = self._lookup_cache[id] selection.append(lookup_rec) return selection def set_selection(self, models): """ Checks items corresponding to the specified models. :param models: List containing model values in the view for selection. :type models: list """ for m in models: search_value = m.value v_items = self._item_model.findItems(search_value) #Loop through result and check items for vi in v_items: if vi.checkState() == Qt.Unchecked: vi.setCheckState(Qt.Checked)
class AbstractSTREnityListView(QListView): """ A widget for listing and selecting one or more STR entities. .. versionadded:: 1.7 """ def __init__(self, parent=None, **kwargs): super(AbstractSTREnityListView, self).__init__(parent) self._model = QStandardItemModel(self) self._model.setColumnCount(1) self.setModel(self._model) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self._model.itemChanged.connect(self._on_item_changed) self._profile = kwargs.get('profile', None) self._social_tenure = kwargs.get('social_tenure', None) # Load appropriate entities to the view if not self._profile is None: self._load_profile_entities() # Load entities in the STR definition if not self._social_tenure is None: self._select_str_entities() def _on_item_changed(self, item): # Emit signals when an item has been (de)selected. To be # implemented by subclasses. pass @property def profile(self): """ :return: Returns the current profile object in the configuration. :rtype: Profile """ return self._profile @profile.setter def profile(self, profile): """ Sets the current profile object in the configuration. :param profile: Profile object. :type profile: Profile """ self._profile = profile self._load_profile_entities() @property def social_tenure(self): """ :return: Returns the profile's social tenure entity. :rtype: SocialTenure """ return self._social_tenure @social_tenure.setter def social_tenure(self, social_tenure): """ Set the social_tenure entity. :param social_tenure: A profile's social tenure entity. :type social_tenure: SocialTenure """ self._social_tenure = social_tenure self._select_str_entities() def _select_str_entities(self): """ Select the entities defined in the STR. E.g. parties for party entity and spatial units for spatial unit entity. Default implementation does nothing, to be implemented by subclasses. """ pass def _load_profile_entities(self): # Reset view self.clear() # Populate entity items in the view for e in self._profile.user_entities(): self._add_entity(e) def _add_entity(self, entity): # Add entity item to view item = QStandardItem( QIcon(':/plugins/stdm/images/icons/table.png'), entity.short_name ) item.setCheckable(True) item.setCheckState(Qt.Unchecked) self._model.appendRow(item) def select_entities(self, entities): """ Checks STR entities in the view and emit the entity_selected signal for each item selected. :param entities: Collection of STR entities. :type entities: list """ # Clear selection self.clear_selection() for e in entities: name = e.short_name self.select_entity(name) def selected_entities(self): """ :return: Returns a list of selected entity short names. :rtype: list """ selected_items = [] for i in range(self._model.rowCount()): item = self._model.item(i) if item.checkState() == Qt.Checked: selected_items.append(item.text()) return selected_items def clear(self): """ Remove all party items in the view. """ self._model.clear() self._model.setColumnCount(1) def clear_selection(self): """ Uncheck all items in the view. """ for i in range(self._model.rowCount()): item = self._model.item(i) if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked) def select_entity(self, name): """ Selects a party entity with the given short name. :param name: Entity short name :type name: str """ items = self._model.findItems(name) if len(items) > 0: item = items[0] if item.checkState() == Qt.Unchecked: item.setCheckState(Qt.Checked) def deselect_entity(self, name): """ Deselects an entity with the given short name. :param name: Entity short name :type name: str """ items = self._model.findItems(name) if len(items) > 0: item = items[0] if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked)
class OWConfusionMatrix(widget.OWWidget): name = "Confusion Matrix" description = "Shows a confusion matrix." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [{"name": "Evaluation Results", "type": Orange.evaluation.testing.Results, "handler": "set_results"}] outputs = [{"name": "Selected Data", "type": Orange.data.Table}] quantities = ["Number of instances", "Observed and expected instances", "Proportion of predicted", "Proportion of true"] selected_learner = settings.Setting([]) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) def __init__(self, parent=None): super().__init__(parent) self.results = None self.learners = [] self._invalidated = False box = gui.widgetBox(self.controlArea, "Learners") self.learners_box = gui.listBox( box, self, "selected_learner", "learners", callback=self._learner_changed ) box = gui.widgetBox(self.controlArea, "Show") combo = gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.widgetBox(self.controlArea, "Selection") gui.button(box, self, "Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "None", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Append class predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Append predicted class probabilities", callback=self._invalidate) b = gui.button(box, self, "Commit", callback=self.commit, default=True) cb = gui.checkBox(box, self, "autocommit", "Commit automatically") gui.setStopper(self, b, cb, "_invalidated", callback=self.commit) grid = QGridLayout() grid.setContentsMargins(0, 0, 0, 0) grid.addWidget(QLabel("Predicted"), 0, 1, Qt.AlignCenter) grid.addWidget(VerticalLabel("Correct Class"), 1, 0, Qt.AlignCenter) self.tablemodel = QStandardItemModel() self.tableview = QTableView( editTriggers=QTableView.NoEditTriggers, ) self.tableview.setModel(self.tablemodel) self.tableview.selectionModel().selectionChanged.connect( self._invalidate ) grid.addWidget(self.tableview, 1, 1) self.mainArea.layout().addLayout(grid) def set_results(self, results): """Set the input results.""" self.clear() self.warning([0, 1]) data = None if results is not None: if results.data is not None: data = results.data if data is not None and \ not isinstance(data.domain.class_var, Orange.data.DiscreteVariable): data = None results = None self.warning( 0, "Confusion Matrix cannot be used for regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is not None: nmodels, ntests = results.predicted.shape headers = class_values + [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'fitter_names' is set in 'Test Learners' widget. if hasattr(results, "fitter_names"): self.learners = results.fitter_names else: self.learners = ["L %i" % (i + 1) for i in range(nmodels)] self.tablemodel.setVerticalHeaderLabels(headers) self.tablemodel.setHorizontalHeaderLabels(headers) self.tablemodel.setRowCount(len(class_values) + 1) self.tablemodel.setColumnCount(len(class_values) + 1) self.selected_learner = [0] self._update() def clear(self): self.learners = [] self.results = None self.data = None self.tablemodel.clear() def select_correct(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) def select_wrong(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) def select_none(self): self.tableview.selectionModel().clear() def commit(self): if self.results and self.data: indices = self.tableview.selectedIndexes() indices = {(ind.row(), ind.column()) for ind in indices} actual = self.results.actual selected_learner = self.selected_learner[0] learner_name = self.learners[selected_learner] predicted = self.results.predicted[selected_learner] selected = [i for i, t in enumerate(zip(actual, predicted)) if t in indices] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values ) metas = metas + (var,) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[selected_learner, selected] extra.append(numpy.array(probs, dtype=object)) pvars = [Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] M = numpy.hstack((M,) + tuple(extra)) domain = Orange.data.Domain( self.data.domain.attributes, self.data.domain.class_vars, metas ) data = Orange.data.Table.from_numpy(domain, X, Y, M) else: data = None self.send("Selected Data", data) self._invalidated = False def _invalidate(self): if self.autocommit: self.commit() else: self._invalidated = True def _learner_changed(self): # The selected learner has changed self._update() def _update(self): # Update the displayed confusion matrix if self.results is not None and self.selected_learner: index = self.selected_learner[0] cmatrix = confusion_matrix(self.results, index) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) total = rowsum.sum() if self.selected_quantity == 0: value = lambda i, j: int(cmatrix[i, j]) elif self.selected_quantity == 1: priors = numpy.outer(rowsum, colsum) / total value = lambda i, j: \ "{} / {:5.3f}".format(cmatrix[i, j], priors[i, j]) elif self.selected_quantity == 2: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i]) if colsum[i] else "N/A") elif self.selected_quantity == 3: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i]) if colsum[i] else "N/A") else: assert False model = self.tablemodel for i, row in enumerate(cmatrix): for j, _ in enumerate(row): item = model.item(i, j) if item is None: item = QStandardItem() item.setData(value(i, j), Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) model.setItem(i, j, item) font = model.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) def sum_item(value): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) return item N = len(colsum) for i in range(N): model.setItem(N, i, sum_item(int(colsum[i]))) model.setItem(i, N, sum_item(int(rowsum[i]))) model.setItem(N, N, sum_item(int(total)))
class QMapManager(QDialog): def __init__(self, config, parent=None): QDialog.__init__(self, parent) curdir = os.path.abspath(os.path.dirname(__file__)) PyQt4.uic.loadUi(os.path.join(curdir, 'manager.ui'), self) self.model = QStandardItemModel() self.projectsmodel = QStandardItemModel() self.projectlist.setModel(self.projectsmodel) self.clientlist.setModel(self.model) self.clientlist.selectionModel().selectionChanged.connect(self.update) self.installbutton.pressed.connect(self.installToClient) self.mapper = QDataWidgetMapper() self.mapper.setModel(self.model) self.mapper.addMapping(self.installpath, 1) self.config = config self.populateProjects() self.populateClients() def installToClient(self): index = self.clientlist.selectionModel().currentIndex() item = self.model.itemFromIndex(index) print "Deploying to " + item.text() build.deployTargetByName(item.text()) def update(self, selected, deselected): index = selected.indexes()[0] self.mapper.setCurrentModelIndex(index) item = self.model.itemFromIndex(index) settings = item.data() for row in xrange(0, self.projectsmodel.rowCount()): index = self.projectsmodel.index(row, 0) item = self.projectsmodel.itemFromIndex(index) item.setCheckState(Qt.Unchecked) projects = settings['projects'] for project in projects: if project == "All": i = 0 while self.projectsmodel.item(i): item = self.projectsmodel.item(i) item.setCheckState(Qt.Checked) i += 1 break projectitem = self.projectsmodel.findItems(project)[0] projectitem.setCheckState(Qt.Checked) def populateClients(self): row = 0 for client, settings in self.config['clients'].iteritems(): name = QStandardItem(client) name.setData(settings) path = QStandardItem(settings['path']) self.model.insertRow(row, [name, path]) row += 1 def populateProjects(self): row = 0 for project in getProjects(): projectitem = QStandardItem(project.name) projectitem.setCheckable(True) self.projectsmodel.insertRow(row, projectitem) row += 1
class PluginRepositoriesGUI(QWidget): PATH_COLUMN = 1 ACTIVE_COLUMN = 0 AUTO_UPDATE_COLUMN = 2 STATUS_COLUMN = 3 addRepository = pyqtSignal() checkForUpdates = pyqtSignal() def __init__(self, logger, parent): super(PluginRepositoriesGUI, self).__init__(parent) self.logger = logger self._gitHandler = GitHandler(logger) layout = QVBoxLayout(self) self._reposTable = QTreeView(self) self._reposTable.setIndentation(0) self._reposTable.header().setStretchLastSection(False) self._reposModel = QStandardItemModel(self._reposTable) self._initModel() self._reposTable.setModel(self._reposModel) self._reposTable.setSelectionMode(QTreeView.ExtendedSelection) self._reposTable.selectionModel().selectionChanged.connect(self._selectionChanged) layout.addWidget(self._reposTable) buttonLayout = QHBoxLayout() addButton = QPushButton("Add...") addButton.clicked.connect(self.addRepository) self._removeButton = QPushButton("Remove") self._removeButton.setEnabled(False) self._removeButton.clicked.connect(self._removeSelected) refreshButton = QPushButton("Check Status") refreshButton.clicked.connect(self.checkForUpdates) buttonLayout.addWidget(addButton) buttonLayout.addWidget(self._removeButton) buttonLayout.addWidget(refreshButton) layout.addLayout(buttonLayout) self._statusWidget = QWidget(self) self._statusWidget.setVisible(False) statusLayout = QHBoxLayout(self._statusWidget) statusLayout.setContentsMargins(0, 0, 0, 0) self._statusLabel = QLabel(self) statusLayout.addWidget(self._statusLabel) layout.addWidget(self._statusWidget) def clear(self): self._initModel() def _updateStatusItem(self, item, path, outdated=None, upToDate=None): # first check fresh results, then the ones from repositories if upToDate and path in upToDate: item.setText(upToDate[path]) if upToDate[path] == GitHandler.UP_TO_DATE_REASON: item.setData(QColor(0, 255, 0), Qt.DecorationRole) else: item.setData(QColor(255, 0, 0), Qt.DecorationRole) elif outdated and path in outdated: item.setText("Repository can be updated") item.setData(QColor(255, 215, 0), Qt.DecorationRole) elif get_settings().get_plugin_repositories().isUpToDate(path): item.setText("No updates (for details, check status)") item.setData(QColor(0, 255, 0), Qt.DecorationRole) elif get_settings().get_plugin_repositories().isOutdated(path): item.setText("Repository can be updated") item.setData(QColor(255, 215, 0), Qt.DecorationRole) else: item.setData(None, Qt.DecorationRole) def updateStatusItems(self, outdated=None, upToDate=None): for row in xrange(self._reposModel.rowCount()): path = convert_string(self._reposModel.item(row, self.PATH_COLUMN).data(Qt.DisplayRole).toString()) self._updateStatusItem(self._reposModel.item(row, self.STATUS_COLUMN), path, outdated, upToDate) def _initModel(self): from PyQt4.QtCore import QStringList self._reposModel.clear() stringList = QStringList([u"Active", u"Path", u"Auto Update", u"Status"]) self._reposModel.setColumnCount(stringList.count()) self._reposModel.setHorizontalHeaderLabels(stringList) def appendRepository(self, path, active, autoUpdate, canAutoUpdate = None): activeItem = QStandardItem() activeItem.setEditable(False) activeItem.setCheckState(Qt.Checked if active else Qt.Unchecked) activeItem.setCheckable(True) pathItem = QStandardItem() pathItem.setData(path, Qt.DisplayRole) pathItem.setEditable(False) autoUpdateItem = QStandardItem() autoUpdateItem.setEditable(False) if canAutoUpdate == None: canAutoUpdate = self._gitHandler.hasGit(path) if canAutoUpdate: autoUpdateItem.setCheckState(Qt.Checked if autoUpdate else Qt.Unchecked) autoUpdateItem.setCheckable(True) statusItem = QStandardItem() self._updateStatusItem(statusItem, path) self._reposModel.appendRow([activeItem, pathItem, autoUpdateItem, statusItem]) def resizeColumns(self): self._reposTable.resizeColumnToContents(self.ACTIVE_COLUMN) self._reposTable.resizeColumnToContents(self.AUTO_UPDATE_COLUMN) self._reposTable.header().setResizeMode(self.PATH_COLUMN, QHeaderView.Stretch) self._reposTable.header().setResizeMode(self.STATUS_COLUMN, QHeaderView.ResizeToContents) def getTable(self): return self._reposTable @loggingSlot(QItemSelection, QItemSelection) def _selectionChanged(self, _sel, _desel): selection = self._reposTable.selectionModel().selectedRows() self._removeButton.setEnabled(len(selection) > 0) @loggingSlot() def _removeSelected(self): selection = self._reposTable.selectionModel().selectedRows() for index in selection: self._reposTable.model().removeRow(index.row()) def setStatus(self, msg, _progress=False): if msg: self._statusLabel.setText(msg) self._statusWidget.setVisible(True) else: self._statusWidget.setVisible(False)
class ModelAtrributesView(QListView): """ Custom QListView implementation that displays checkable model attributes. """ def __init__(self,parent=None,dataModel = None): QListView.__init__(self, parent) self._dataModel = dataModel self._selectedDisplayMapping = OrderedDict() self._modelDisplayMapping = OrderedDict() self._attrModel = QStandardItemModel(self) def dataModel(self): """ Returns the data model instance. """ return self._dataModel def setDataModel(self,dataModel): """ Sets the data model. Should be a callable class rather than the class. instance. """ if callable(dataModel): self._dataModel = dataModel else: self._dataModel = dataModel.__class__ def modelDisplayMapping(self): """ Returns the column name and display name collection. """ return self._modelDisplayMapping def setModelDisplayMapping(self, dataMapping): """ Sets the mapping dictionary for the table object """ if dataMapping != None: self._modelDisplayMapping=dataMapping def load(self, sort=False): """ Load the model's attributes into the list view. """ if self._dataModel == None: return try: self._loadAttrs(self._dataModel.displayMapping(), sort) except AttributeError: #Ignore error if model does not contain the displayMapping static method pass def load_mapping(self, mapping, sort=False): """ Load collection containing column name and corresponding display name. """ self._modelDisplayMapping = mapping self._loadAttrs(mapping, sort) def sort(self): """ Sorts display name in ascending order. """ self._attrModel.sort(0) def _loadAttrs(self, attrMapping, sort=False): """ Loads display mapping into the list view. Specify to sort display names in ascending order once items have been added to the model. """ self._attrModel.clear() self._attrModel.setColumnCount(2) for attrName,displayName in attrMapping.iteritems(): #Exclude row ID in the list, other unique identifier attributes in the model can be used if attrName != "id": displayNameItem = QStandardItem(displayName) displayNameItem.setCheckable(True) attrNameItem = QStandardItem(attrName) self._attrModel.appendRow([displayNameItem,attrNameItem]) self.setModel(self._attrModel) if sort: self._attrModel.sort(0) def selectedMappings(self): """ Return a dictionary of field names and their corresponding display values. """ selectedAttrs = {} for i in range(self._attrModel.rowCount()): displayNameItem = self._attrModel.item(i,0) if displayNameItem.checkState() == Qt.Checked: attrNameItem = self._attrModel.item(i,1) selectedAttrs[attrNameItem.text()] = displayNameItem.text() return selectedAttrs
class SubPowerWidget(QWidget): """ @brief Zeigt alle Unterkräfte in einer Baumstruktur an. """ def __init__(self, template, character, parent=None): super(SubPowerWidget, self).__init__(parent) self.__storage = template self.__character = character self.__model = QStandardItemModel() # Das ungenutzte Model dient dazu, alle Unterkräfte aufzunehmen, die ich nicht darstellen möchte. Ist einfacher, als diese im View zu verstecken. self.__modelUnused = QStandardItemModel() self._layout = QVBoxLayout() self.setLayout(self._layout) self.__view = QTreeView() self.__view.setHeaderHidden(True) self.__view.setModel(self.__model) self._layout.addWidget(self.__view) self._typ = "Subpower" categories = self.__storage.categories(self._typ) self.__items = {} self.__rootItem = QStandardItem() self.__rootItem = self.__model.invisibleRootItem() self.__rootItemUnused = QStandardItem() self.__rootItemUnused = self.__modelUnused.invisibleRootItem() for item in categories: categoryItem = QStandardItem(item) self.__rootItem.appendRow(categoryItem) ## Ich benötige diese Items auch im ungenutzten Model. categoryItemUnused = QStandardItem(item) self.__rootItemUnused.appendRow(categoryItemUnused) traitList = list(self.__character.traits[self._typ][item].items()) traitList.sort() for trait in traitList: traitItem = QStandardItem(trait[1].name) traitItem.setCheckable(True) ## Unhashable Type self.__items[trait[1]] = traitItem categoryItem.appendRow(traitItem) ## Funktioniert mit PySide nicht: #trait[1].availableChanged.connect(traitItem.setEnabled) ## Funktioniert auch mit PySide: trait[1].availableChanged.connect( lambda enable, item=traitItem: item.setEnabled(enable)) trait[1].valueChanged.connect(lambda val, trait=trait[ 1], item=traitItem: self.__setItemValue(trait, item)) self.__model.itemChanged.connect(self.__getItemValue) self.__character.speciesChanged.connect(self.hideOrShowToolPage) self.__character.breedChanged.connect(self.hideOrShowToolPage) self.__character.factionChanged.connect(self.hideOrShowToolPage) def __setItemValue(self, trait, item): """ Setzt den Wert der Angezeigten Items. """ if trait.value == 0: item.setCheckState(Qt.Unchecked) elif trait.value == 1: item.setCheckState(Qt.PartiallyChecked) else: item.setCheckState(Qt.Checked) def __getItemValue(self, item): """ Setzt den Wert der Eigenschaft im Speicher. """ for trait in self.__items.items(): if id(trait[1]) == id(item): trait[0].value = item.checkState() break def hideOrShowToolPage(self, res): """ Alle Eigenschaften, die nicht zur Verfügung stehen, werden verborgen, indem sie in ein anderes Model verschoben werden. \bug Möglicher Fehler in PySide: Der Aufruf von QStandardItem.model() führt beim Beenden des Programms zu einem Segmentation Fault. """ # Versteckt alle Unterkräfte, die zu gewähltem Charakter nicht passen. for item in self.__items.items(): if ((item[0].species and item[0].species != self.__character.species) or (item[0].only and self.__character.breed not in item[0].only and self.__character.faction not in item[0].only)): #self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), True) #Debug.debug(item[1].model()) ## Hier wird beispielsweise besagter Aufruf getätigt, der zu einem segfault führt. if item[1].model() == self.__model: parent = item[1].parent() itemUnused = parent.takeRow(item[1].index().row()) parentUnused = self.__modelUnused.findItems( parent.text())[0] parentUnused.appendRow(itemUnused) else: #self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), False) if item[1].model() == self.__modelUnused: parent = item[1].parent() itemUsed = parent.takeRow(item[1].index().row()) parentUsed = self.__model.findItems(parent.text())[0] parentUsed.appendRow(itemUsed) ## Versteckt alle Elternzeilen, wenn sie keine Kinder enthalten. for i in range(self.__model.rowCount()): categoryItem = self.__model.item(i) if categoryItem.hasChildren(): self.__view.setRowHidden(categoryItem.index().row(), self.__rootItem.index(), False) else: self.__view.setRowHidden(categoryItem.index().row(), self.__rootItem.index(), True)
class OrderSelectorModel(QObject): """""" #---------------------------------------------------------------------- def __init__(self, full_string_list, init_selected_string_list=None, permanently_selected_string_list=None): """Constructor""" QObject.__init__(self) self.output = [] if not self.hasNoDuplicateStrings(full_string_list): raise ValueError('Duplicate strings detected in full string list.') else: self.full_string_list = full_string_list[:] if init_selected_string_list is not None: if not self.allStringsInList1FoundInList2( init_selected_string_list, self.full_string_list): raise ValueError('Some of the strings in initially selected string list are not in full string list.') else: init_selected_string_list = [] if permanently_selected_string_list is not None: if not self.allStringsInList1FoundInList2( permanently_selected_string_list, init_selected_string_list): raise ValueError('Some of the strings in permanently selected string list are not in initially selected string list.') else: permanently_selected_string_list = [] self.permanently_selected_string_list = permanently_selected_string_list[:] self.model_Selected = QStandardItemModel() self.model_NotSelected = QStandardItemModel() Selected_item_list = [None for s in init_selected_string_list] NotSelected_item_list = [] for s in self.full_string_list: item = QStandardItem(s) try: Selected_item_list[init_selected_string_list.index(s)] = item except: NotSelected_item_list.append(item) for item in NotSelected_item_list: self.model_NotSelected.appendRow(item) for item in Selected_item_list: self.model_Selected.appendRow(item) #---------------------------------------------------------------------- def getSelectedList(self): """""" selectedList = [] for i in range(self.model_Selected.rowCount()): selectedList.append(self.model_Selected.item(i,0).text()) return selectedList #---------------------------------------------------------------------- def hasNoDuplicateStrings(self, full_string_list): """""" str_list = full_string_list str_set = set(full_string_list) if len(str_list) == len(str_set): return True else: return False #---------------------------------------------------------------------- def allStringsInList1FoundInList2(self, str_list_1, str_list_2): """""" stringsNotFound = [ s for s in str_list_1 if s not in str_list_2 ] if stringsNotFound != []: return False else: return True
class InputDialog(GenericDialog): TBL_HEADER_LABEL=["Input Mesh", "Output group name"] def __init__(self, parent=None, name="InputDialog", modal=0): """ This initializes a dialog windows to define the input data of the plugin function. The input data consist in a list of meshes characterizes each by a name, a pointer to the smesh servant object, a type and a group name (see data model in the inputdata.py). """ GenericDialog.__init__(self, parent, name, modal) # Set up the user interface from Designer. self.__ui = Ui_InputFrame() # BE CAREFULL HERE, the ui form is NOT drawn in the global # dialog (already containing some generic widgets) but in the # center panel created in the GenericDialog as a void # container for the form. The InputFrame form is supposed # here to create only the widgets to be placed in the center # panel. Then, the setupUi function of this form draws itself # in the specified panel, i.e. the panel returned by # self.getPanel(). self.__ui.setupUi(self.getPanel()) self.setWindowTitle("Specification of input files") # The icon are supposed to be located in the plugin folder, # i.e. in the same folder than this python module file iconfolder=os.path.dirname(os.path.abspath(__file__)) icon = QIcon() icon.addFile(os.path.join(iconfolder,"select.png")) self.__ui.btnSmeshObject.setIcon(icon) icon = QIcon() icon.addFile(os.path.join(iconfolder,"addinput.png")) self.__ui.btnAddInput.setIcon(icon) icon = QIcon() icon.addFile(os.path.join(iconfolder,"deleteinput.png")) self.__ui.btnDeleteInput.setIcon(icon) # We specify here the items in the combo box (even if already # defined in the designer) so that we can be sure of the item # indexation. self.MESHTYPE_ICONS = {} meshTypeIndex = InputData.MESHTYPES.CONCRETE self.__ui.cmbMeshType.setItemText(meshTypeIndex, "Béton") icon = QIcon() icon.addFile(os.path.join(iconfolder,"concrete.png")) self.__ui.cmbMeshType.setItemIcon(meshTypeIndex, icon) self.MESHTYPE_ICONS[meshTypeIndex] = icon meshTypeIndex = InputData.MESHTYPES.STEELBAR self.__ui.cmbMeshType.setItemText(meshTypeIndex, "Acier") icon = QIcon() icon.addFile(os.path.join(iconfolder,"steelbar.png")) self.__ui.cmbMeshType.setItemIcon(meshTypeIndex, icon) self.MESHTYPE_ICONS[meshTypeIndex] = icon # The click on btnSmeshObject (signal clicked() emitted by the # button btnSmeshObject) is connected to the slot # onSelectSmeshObject, etc ... self.connect(self.__ui.btnSmeshObject, SIGNAL('clicked()'), self.onSelectSmeshObject ) self.connect(self.__ui.btnAddInput, SIGNAL('clicked()'), self.onAddInput ) self.connect(self.__ui.btnDeleteInput, SIGNAL('clicked()'), self.onDeleteInput ) # Set up the model of the Qt table list self.__inputModel = QStandardItemModel(0,2) self.__inputModel.setHorizontalHeaderLabels(InputDialog.TBL_HEADER_LABEL) self.__ui.tblListInput.setModel(self.__inputModel) self.__ui.tblListInput.verticalHeader().hide() self.__ui.tblListInput.horizontalHeader().setStretchLastSection(True) # Note that the type is not display explicitly in the Qt table # because it is specified using an icon on the text of the # name item. # Note that PADDER does not support group name longer than 8 # characters. We apply then this limit in the gui field. self.__ui.txtGroupName.setMaxLength(GROUPNAME_MAXLENGTH) self.clear() self.smeshStudyTool = SMeshStudyTools() def clear(self): """ This function clears the data gui area and associated values. """ self.__ui.txtSmeshObject.setText("") self.__ui.txtGroupName.setText("") self.__inputModel.clear() self.__inputModel.setHorizontalHeaderLabels(InputDialog.TBL_HEADER_LABEL) if not DEBUG_MODE: self.__ui.txtSmeshObject.setEnabled(False) self.__ui.btnAddInput.setEnabled(False) self.__selectedMesh = None self.__dictInputData = {} self.__nbConcreteMesh = 0 self.__nbSteelbarMesh = 0 def accept(self): """ This function is the slot connected to the button OK """ # The dialog is raised in a non modal mode to get # interactivity with the parents windows. Then we have to emit # a signal to warn the parent observer that the dialog has # been validated so that it can process the event GenericDialog.accept(self) if self.wasOk(): self.emit(SIGNAL('inputValidated()')) def onSelectSmeshObject(self): ''' This function is the slot connected on the mesh selection button. It memorizes the selected mesh and put its name in the text field of the dialog box. ''' mySObject, myEntry = guihelper.getSObjectSelected() if CORBA.is_nil(mySObject): self.__ui.txtSmeshObject.setText("You must choose a mesh") self.__ui.txtGroupName.setText("") self.__ui.txtSmeshObject.setEnabled(False) self.__ui.btnAddInput.setEnabled(False) self.__selectedMesh = None return self.smeshStudyTool.updateStudy(studyedit.getActiveStudyId()) self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject) if CORBA.is_nil(self.__selectedMesh): self.__ui.txtSmeshObject.setText("The selected object is not a mesh") self.__ui.txtGroupName.setText("") self.__ui.txtSmeshObject.setEnabled(False) self.__ui.btnAddInput.setEnabled(False) self.__selectedMesh = None return myName = mySObject.GetName() self.__ui.txtSmeshObject.setText(myName) self.__ui.txtSmeshObject.setEnabled(True) self.__ui.btnAddInput.setEnabled(True) # We can suggest a default group name from the mesh name self.__ui.txtGroupName.setText(myName) def onAddInput(self): """ This function is the slot connected to the Add button. It creates a new entry in the list of input data, or updates this entry if it already exists. """ meshName = str(self.__ui.txtSmeshObject.text().trimmed()) meshObject = self.__selectedMesh meshType = self.__ui.cmbMeshType.currentIndex() groupName = str(self.__ui.txtGroupName.text().trimmed()) self.__addInputInGui(meshName, meshObject, meshType, groupName) self.__addInputInMap(meshName, meshObject, meshType, groupName) def __addInputInGui(self, meshName, meshObject, meshType, groupName): """ This function adds an entry with the specified data int the GUI table (for data visualization purpose). """ # The mesh name is used as the key index in the model. We have # to check first if this item already exists in the list. tblItems = self.__inputModel.findItems(meshName) row = self.__inputModel.rowCount() if not tblItems: tblItems = [] tblItems.append(QStandardItem()) # input mesh name tblItems.append(QStandardItem()) # output group name else: row = tblItems[0].index().row() tblItems.append(self.__inputModel.item(row,1)) tblItems[0].setText(meshName) tblItems[0].setIcon(self.MESHTYPE_ICONS[meshType]) tblItems[1].setText(groupName) self.__inputModel.setItem(row,0,tblItems[0]) self.__inputModel.setItem(row,1,tblItems[1]) self.__ui.tblListInput.setCurrentIndex(tblItems[0].index()) def __addInputInMap(self, meshName, meshObject, meshType, groupName): """ This function adds an entry with the specified data in the internal map (for data management purpose). """ # if the entry already exists, we remove it to replace by a # new one if self.__dictInputData.has_key(meshName): self.__delInputFromMap(meshName) inputData = InputData() inputData.meshName = meshName inputData.meshObject = meshObject inputData.meshType = meshType inputData.groupName = groupName # The key of the map is the mesh name self.__dictInputData[meshName] = inputData if inputData.meshType == InputData.MESHTYPES.CONCRETE: self.__nbConcreteMesh += 1 else: self.__nbSteelbarMesh += 1 print inputData print "meshType = ",inputData.meshType print "nb concrete mesh ",self.__nbConcreteMesh print "nb steelbar mesh ",self.__nbSteelbarMesh def onDeleteInput(self): """ This function is the slot connected to the Delete button. It remove from the data list the entry selected in the Qt table. """ selectedIdx = self.__ui.tblListInput.selectedIndexes() if selectedIdx: row = selectedIdx[0].row() tblItem = self.__inputModel.item(row,0) meshName = str(tblItem.text()) self.__inputModel.takeRow(row) # Don't forget to remove this entry from the mesh object # internal dictionnary self.__delInputFromMap(meshName) def __delInputFromMap(self, meshName): """ This function removes the specified entry from the internal map (for data management purpose) """ inputData = self.__dictInputData.pop(meshName) if inputData.meshType == InputData.MESHTYPES.CONCRETE: self.__nbConcreteMesh -= 1 else: self.__nbSteelbarMesh -= 1 print inputData print "nb concrete mesh ",self.__nbConcreteMesh print "nb steelbar mesh ",self.__nbSteelbarMesh def setData(self, listInputData=[]): """ This function fills the dialog widgets with values provided by the specified data list. """ self.clear() for inputData in listInputData: meshName = inputData.meshName meshObject = inputData.meshObject meshType = inputData.meshType groupName = inputData.groupName self.__addInputInGui(meshName, meshObject, meshType, groupName) self.__addInputInMap(meshName, meshObject, meshType, groupName) if not DEBUG_MODE: self.onSelectSmeshObject() def getData(self): """ This function returns a list of InputData that corresponds to the data in the dialog widgets of the current dialog. """ # Note that the values() function returns a copy of the list # of values. return self.__dictInputData.values() def checkData(self): """ This function checks if the data are valid, from the dialog window point of view. """ if self.__nbConcreteMesh == 0 and self.__nbSteelbarMesh == 0: self.checkDataMessage = "You must define at least one mesh (CONCRETE or STEELBAR)" return False if self.__nbConcreteMesh > 1: self.checkDataMessage = "You define multiple CONCRETE meshes." self.checkDataMessage += "You should verify first that your version of PADDER support this configuration." # just warn the user, but don't block QMessageBox.information(self, "Info", self.checkDataMessage) return True return True
class Terminals(QWidget): ready = pyqtSignal(bool) def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = uic.loadUiType('terminal.ui')[0]() self.ui.setupUi(self) self.notifier = QSystemTrayIcon(QIcon('arrow-up-icon.png'), self) self.notifier.show() self.model = None self.mainloop = None self.delegate = None def test_display(self): if self.mainloop: self.mainloop.test_display() def update_device_config(self): if self.mainloop: self.mainloop.update_config() def terminal_open(self, addr): if self.mainloop: self.mainloop.terminal_open(addr) def terminal_close(self, addr): if self.mainloop: self.mainloop.terminal_close(addr) def start_mainloop(self): if self.mainloop is None: self.mainloop = Mainloop(parent=self) self.mainloop.ready.connect(self.on_mainloop_ready) self.mainloop.notify.connect(lambda title, msg: self.notifier.showMessage(title, msg)) self.mainloop.start() def stop_mainloop(self): if self.mainloop: self.mainloop.state.disconnect() self.mainloop.ready.disconnect() self.mainloop.notify.disconnect() [self.ui.terminals.closePersistentEditor(self.model.index(row, 0)) for row in xrange(self.model.rowCount())] self.mainloop.stop() self.mainloop = None def update_model(self): self.stop_mainloop() self.start_mainloop() def on_mainloop_ready(self, ok, titles): if ok: self.model = QStandardItemModel(len(titles), 1) [self.model.setItem(i, QStandardItem(str(addr))) for i, addr in enumerate(titles.keys())] self.delegate = TerminalDelegate(self.mainloop, titles) self.mainloop.report.connect(self.delegate.report) self.mainloop.state.connect(self.delegate.state) self.ui.terminals.setModel(self.model) self.ui.terminals.setItemDelegateForColumn(0, self.delegate) [self.ui.terminals.openPersistentEditor(self.model.index(row, 0)) for row in xrange(self.model.rowCount())] self.mainloop.db.free_places_update.connect(self.ui.free_places.setValue) self.mainloop.update_config() else: self.model = None self.mainloop = None self.ready.emit(ok)
class OWConfusionMatrix(widget.OWWidget): name = "Confusion Matrix" description = "Shows a confusion matrix." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [{ "name": "Evaluation Results", "type": Orange.evaluation.Results, "handler": "set_results" }] outputs = [{"name": "Selected Data", "type": Orange.data.Table}] quantities = [ "Number of instances", "Proportion of predicted", "Proportion of actual" ] selected_learner = settings.Setting([]) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) def __init__(self, parent=None): super().__init__(parent) self.data = None self.results = None self.learners = [] box = gui.widgetBox(self.controlArea, "Learners") self.learners_box = gui.listBox(box, self, "selected_learner", "learners", callback=self._learner_changed) box = gui.widgetBox(self.controlArea, "Show") gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.widgetBox(self.controlArea, "Select") gui.button(box, self, "Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "None", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Probabilities", callback=self._invalidate) gui.auto_commit(self.controlArea, self, "autocommit", "Send Data", "Auto send is on") grid = QGridLayout() grid.setContentsMargins(0, 0, 0, 0) grid.addWidget(QLabel("Predicted"), 0, 1, Qt.AlignCenter) grid.addWidget(VerticalLabel("Actual Class"), 1, 0, Qt.AlignCenter) self.tablemodel = QStandardItemModel() self.tableview = QTableView(editTriggers=QTableView.NoEditTriggers) self.tableview.setModel(self.tablemodel) self.tableview.selectionModel().selectionChanged.connect( self._invalidate) grid.addWidget(self.tableview, 1, 1) self.mainArea.layout().addLayout(grid) def set_results(self, results): """Set the input results.""" self.clear() self.warning([0, 1]) data = None if results is not None: if results.data is not None: data = results.data if data is not None and \ not isinstance(data.domain.class_var, Orange.data.DiscreteVariable): data = None results = None self.warning( 0, "Confusion Matrix cannot be used for regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is not None: nmodels, ntests = results.predicted.shape headers = class_values + [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'learner_names' is set in 'Test Learners' widget. if hasattr(results, "learner_names"): self.learners = results.learner_names else: self.learners = ["L %i" % (i + 1) for i in range(nmodels)] self.tablemodel.setVerticalHeaderLabels(headers) self.tablemodel.setHorizontalHeaderLabels(headers) self.tablemodel.setRowCount(len(class_values) + 1) self.tablemodel.setColumnCount(len(class_values) + 1) self.selected_learner = [0] self._update() def clear(self): self.results = None self.data = None self.tablemodel.clear() # Clear learners last. This action will invoke `_learner_changed` # method self.learners = [] def select_correct(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_wrong(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_none(self): self.tableview.selectionModel().clear() def commit(self): if self.results is not None and self.data is not None \ and self.selected_learner: indices = self.tableview.selectedIndexes() indices = {(ind.row(), ind.column()) for ind in indices} actual = self.results.actual selected_learner = self.selected_learner[0] learner_name = self.learners[selected_learner] predicted = self.results.predicted[selected_learner] selected = [ i for i, t in enumerate(zip(actual, predicted)) if t in indices ] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values) metas = metas + (var, ) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[selected_learner, selected] extra.append(numpy.array(probs, dtype=object)) pvars = [ Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values ] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] row_ids = self.data.ids[row_indices] M = numpy.hstack((M, ) + tuple(extra)) domain = Orange.data.Domain(self.data.domain.attributes, self.data.domain.class_vars, metas) data = Orange.data.Table.from_numpy(domain, X, Y, M) data.ids = row_ids data.name = learner_name else: data = None self.send("Selected Data", data) def _invalidate(self): self.commit() def _learner_changed(self): # The selected learner has changed self._update() self._invalidate() def _update(self): # Update the displayed confusion matrix if self.results is not None and self.selected_learner: index = self.selected_learner[0] cmatrix = confusion_matrix(self.results, index) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) total = rowsum.sum() if self.selected_quantity == 0: value = lambda i, j: int(cmatrix[i, j]) elif self.selected_quantity == 1: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i]) if colsum[i] else "N/A") elif self.selected_quantity == 2: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i]) if colsum[i] else "N/A") else: assert False model = self.tablemodel for i, row in enumerate(cmatrix): for j, _ in enumerate(row): item = model.item(i, j) if item is None: item = QStandardItem() item.setData(value(i, j), Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) model.setItem(i, j, item) font = model.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) def sum_item(value): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) return item N = len(colsum) for i in range(N): model.setItem(N, i, sum_item(int(colsum[i]))) model.setItem(i, N, sum_item(int(rowsum[i]))) model.setItem(N, N, sum_item(int(total)))
class CandidateCrawlerUI(object): def setupUi(self, MainWindow): self.centralwidget = QtGui.QWidget(MainWindow) self.qbox = QBoxLayout(QBoxLayout.TopToBottom, self.centralwidget) self.centralwidget.setLayout(self.qbox) #####Mots-clés### self.keywords_label = QtGui.QLabel(self.centralwidget) self.keywords_label.setText(_translate("AdminWindow", "Mots-clés de recherche", None)) self.keywords_help = QtGui.QPushButton(self.centralwidget) self.keywords_help.setIcon(QIcon('./share/icon/point interrogation.png')) self.keywords_help.setIconSize(QSize(10,10)) self.hbox_keywords = QtGui.QHBoxLayout() self.hbox_keywords.addWidget(self.keywords_label) self.hbox_keywords.addWidget(self.keywords_help) self.hbox_keywords.setContentsMargins(0, 0, 120, 0) self.keywords_entry = QtGui.QLineEdit(self.centralwidget) self.vbox_keywords = QtGui.QVBoxLayout() self.vbox_keywords.addLayout(self.hbox_keywords) self.vbox_keywords.addWidget(self.keywords_entry) self.vbox_keywords.setContentsMargins(0, 0, 0, 5) ###Région### self.region_label = QtGui.QLabel(self.centralwidget) self.region_label.setText(_translate("AdminWindow", "Région (5 choix maximum)", None)) self.region_list = QtGui.QListView(self.centralwidget) self.vbox_region = QtGui.QVBoxLayout() self.vbox_region.addWidget(self.region_label) self.vbox_region.addWidget(self.region_list) self.vbox_region.setContentsMargins(0, 0, 0, 5) ###Mobilité### self.mobilite_label = QtGui.QLabel(self.centralwidget) self.mobilite_label.setText(_translate("AdminWindow", "Mobilité", None)) self.mobilite_combobox = QtGui.QComboBox(self.centralwidget) self.vbox_mobilite = QtGui.QVBoxLayout() self.vbox_mobilite.addWidget(self.mobilite_label) self.vbox_mobilite.addWidget(self.mobilite_combobox) self.vbox_mobilite.setContentsMargins(0, 0, 0, 5) ###Salaire### self.salaire_label = QtGui.QLabel(self.centralwidget) self.salaire_label.setText(_translate("AdminWindow", "Salaire", None)) self.salaire_combobox = QtGui.QComboBox(self.centralwidget) self.vbox_salaire = QtGui.QVBoxLayout() self.vbox_salaire.addWidget(self.salaire_label) self.vbox_salaire.addWidget(self.salaire_combobox) self.vbox_salaire.setContentsMargins(0, 0, 0, 5) ###Disponibilité### self.disponibilite_label = QtGui.QLabel(self.centralwidget) self.disponibilite_label.setText(_translate("AdminWindow", "Disponibilité", None)) self.disponibilite_list = QtGui.QListView(self.centralwidget) self.vbox_disponibilite = QtGui.QVBoxLayout() self.vbox_disponibilite.addWidget(self.disponibilite_label) self.vbox_disponibilite.addWidget(self.disponibilite_list) self.vbox_disponibilite.setContentsMargins(0, 0, 0, 5) ###Fraîcheur### self.fraicheur_label = QtGui.QLabel(self.centralwidget) self.fraicheur_label.setText(_translate("AdminWindow", "Fraîcheur", None)) self.fraicheur_combobox = QtGui.QComboBox(self.centralwidget) self.vbox_fraicheur = QtGui.QVBoxLayout() self.vbox_fraicheur.addWidget(self.fraicheur_label) self.vbox_fraicheur.addWidget(self.fraicheur_combobox) self.vbox_fraicheur.setContentsMargins(0, 0, 0, 5) ###Nombre de CVs### self.cv_number_label = QtGui.QLabel(self.centralwidget) self.cv_number_label.setText(_translate("AdminWindow", "Nombre de CV", None)) self.cv_number_entry = QtGui.QLineEdit(self.centralwidget) self.cv_number_entry.setInputMethodHints(QtCore.Qt.ImhNone) self.cv_number_entry.setText("50") self.vbox_cv_number = QtGui.QVBoxLayout() self.vbox_cv_number.addWidget(self.cv_number_label) self.vbox_cv_number.addWidget(self.cv_number_entry) self.vbox_cv_number.setContentsMargins(0, 0, 0, 5) ###Progression### self.progression_label = QtGui.QLabel(self.centralwidget) self.progression_label.setText(_translate("AdminWindow", "Progression", None)) self.progression_text = QtGui.QTextBrowser(self.centralwidget) self.vbox_progression = QtGui.QVBoxLayout() self.vbox_progression.addWidget(self.progression_label) self.vbox_progression.addWidget(self.progression_text) self.vbox_progression.setContentsMargins(0, 0, 0, 5) ###Bouton de lancement### self.run_button = QtGui.QPushButton(self.centralwidget) self.run_button.setText(_translate("AdminWindow", "Lancer la recherche", None)) ###Ajout a la fenetre principale### self.qbox.addLayout(self.vbox_keywords) self.qbox.addLayout(self.vbox_region) self.qbox.addLayout(self.vbox_mobilite) self.qbox.addLayout(self.vbox_salaire) self.qbox.addLayout(self.vbox_disponibilite) self.qbox.addLayout(self.vbox_fraicheur) self.qbox.addLayout(self.vbox_cv_number) self.qbox.addLayout(self.vbox_progression) self.qbox.addWidget(self.run_button) MainWindow.setCentralWidget(self.centralwidget) ###Barre de menu### MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(MainWindow) self.menuFichier = QtGui.QMenu(self.menubar) self.menuEdition = QtGui.QMenu(self.menubar) self.menuAide = QtGui.QMenu(self.menubar) MainWindow.setMenuBar(self.menubar) self.about_action = QtGui.QAction(MainWindow) self.admin_action = QtGui.QAction(MainWindow) self.exit_action = QtGui.QAction(MainWindow) self.menuFichier.addAction(self.admin_action) self.menuFichier.addAction(self.exit_action) self.menuAide.addAction(self.about_action) self.menubar.addAction(self.menuFichier.menuAction()) self.menubar.addAction(self.menuAide.menuAction()) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) # Values for combobox staticsxmlfile = "statics.xml" region_list = tuple(toolbox.xml_reader(staticsxmlfile, "regions").split(',')) mobilite_list = tuple(toolbox.xml_reader(staticsxmlfile, "mobilite").split(',')) salaire_list = tuple(toolbox.xml_reader(staticsxmlfile, "salaire").split(',')) disponibilite_list = tuple(toolbox.xml_reader(staticsxmlfile, "disponibilite").split(',')) fraicheur_list = tuple(toolbox.xml_reader(staticsxmlfile, "fraicheur").split(',')) self.model = QStandardItemModel(self.region_list) for region in region_list: item = QStandardItem(region) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(QVariant(Qt.Unchecked), Qt.CheckStateRole) self.model.appendRow(item) self.region_list.setModel(self.model) self.model2 = QStandardItemModel(self.disponibilite_list) for disponibilite in disponibilite_list: item = QStandardItem(disponibilite) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(QVariant(Qt.Unchecked), Qt.CheckStateRole) self.model2.appendRow(item) self.disponibilite_list.setModel(self.model2) for element in mobilite_list: self.mobilite_combobox.addItem(element) for element in salaire_list: self.salaire_combobox.addItem(element) for element in fraicheur_list: self.fraicheur_combobox.addItem(element) # Action attached to buttons #################################################################### self.about_action.triggered.connect(self.about_window) self.admin_action.triggered.connect(self.admin_window) self.exit_action.triggered.connect(self.close) self.run_button.clicked.connect(self.run_program) self.keywords_help.clicked.connect(self.ouvrirDialogue) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(_translate("MainWindow", "Candidate Crawler APEC", None)) self.menuFichier.setTitle(_translate("MainWindow", "Fichier", None)) self.menuAide.setTitle(_translate("MainWindow", "Aide", None)) self.about_action.setText(_translate("MainWindow", "A propos", None)) self.admin_action.setText(_translate("MainWindow", "Administration", None)) self.exit_action.setText(_translate("MainWindow", "Quitter", None)) # Methods for class CandidateCrawlerUI def about_window(self): """Method to generate About window""" self.about_w = About_window.AboutWindowGUI() self.about_w.show() def admin_window(self): """Method to generate About window""" self.admin_w = Admin_window.AdminWindowGUI() self.admin_w.show() def reset(self): """Method to reset main window""" self.progression_text.clear() def close(self): """Method to close main window""" self.close() def ouvrirDialogue(self): QMessageBox.information(self, self.trUtf8("Aide mots-clés"),self.trUtf8("Vous pouvez entrer plusieurs mots-clés, sans accents, en les séparant par des espaces.")) def _entries_retriever(self): """Method to get user entries""" self.keywords = self.trUtf8(self.keywords_entry.text()) self.region = [] for row in range(self.model.rowCount()): item = self.model.item(row) if item.checkState() == QtCore.Qt.Checked: self.region = [str(item.text())]+self.region self.mobilite = self.mobilite_combobox.currentText() self.salaire = self.salaire_combobox.currentText() self.disponibilite = [] for row in range(self.model2.rowCount()): item = self.model2.item(row) if item.checkState() == QtCore.Qt.Checked: self.disponibilite = [str(item.text())]+self.disponibilite self.fraicheur = self.fraicheur_combobox.currentText() self.nombreCV = self.trUtf8(self.cv_number_entry.text()) def _entries_checker(self): """Method to check user entries""" error_code = False error_list = [] if self.keywords[0] == "": error_code = True error_list.append(_translate("MainWindow", "Veuillez entrer des mots-clés", None)) if self.nombreCV[0] == "": error_code = True error_list.append(_translate("MainWindow", "Veuillez entrer un nombre de CVs", None)) return error_code, error_list def run_program(self): """Method to run program on tab1: ponctual search""" self.progression_text.append("Lancement du programme") self.progression_text.append("Programme en cours ...") app.processEvents() # Window refresh try: self._entries_retriever() if self._entries_checker()[0]: self.progression_text.setTextColor(QtGui.QColor("red")) for element in self._entries_checker()[1]: self.progression_text.append(element) self.progression_text.setTextColor(QtGui.QColor("black")) self.progression_text.append(_translate("MainWindow", "Programme stoppé", None)) return runapp = core.CandidateCrawlerCore(toolbox.getconfigvalue("APEC", "login"), toolbox.getconfigvalue("APEC", "password"),self.keywords, self.region , self.mobilite, self.salaire, self.disponibilite, self.fraicheur, self.nombreCV) print(self.keywords) print(self.region) print(self.mobilite) print(self.salaire) print(self.disponibilite) print(self.fraicheur) print(self.nombreCV) runapp.crawl() self.progression_text.append(self.trUtf8("Fin du programme\n")) except: self.progression_text.append(self.trUtf8("Oups, quelque chose s'est mal passé")) self.progression_text.append(self.trUtf8("Veuillez vérifier les champs de l'adiministration")) self.progression_text.append(self.trUtf8("Fin du programme\n")) raise
class QMapManager(QDialog): def __init__(self, config, parent=None): QDialog.__init__(self, parent) curdir = os.path.abspath(os.path.dirname(__file__)) PyQt4.uic.loadUi(os.path.join(curdir,'manager.ui'), self) self.model = QStandardItemModel() self.projectsmodel = QStandardItemModel() self.projectlist.setModel(self.projectsmodel) self.clientlist.setModel(self.model) self.clientlist.selectionModel().selectionChanged.connect(self.update) self.installbutton.pressed.connect(self.installToClient) self.mapper = QDataWidgetMapper() self.mapper.setModel(self.model) self.mapper.addMapping(self.installpath, 1) self.config = config self.populateProjects() self.populateClients() def installToClient(self): index = self.clientlist.selectionModel().currentIndex() item = self.model.itemFromIndex(index) print "Deploying to " + item.text() build.deployTargetByName(item.text()) def update(self, selected, deselected ): index = selected.indexes()[0] self.mapper.setCurrentModelIndex(index) item = self.model.itemFromIndex(index) settings = item.data() for row in xrange(0,self.projectsmodel.rowCount()): index = self.projectsmodel.index(row, 0) item = self.projectsmodel.itemFromIndex(index) item.setCheckState(Qt.Unchecked) projects = settings['projects'] for project in projects: if project == "All": i = 0 while self.projectsmodel.item(i): item = self.projectsmodel.item(i) item.setCheckState(Qt.Checked) i += 1 break projectitem = self.projectsmodel.findItems(project)[0] projectitem.setCheckState(Qt.Checked) def populateClients(self): row = 0 for client, settings in self.config['clients'].iteritems(): name = QStandardItem(client) name.setData(settings) path = QStandardItem(settings['path']) self.model.insertRow(row, [name, path]) row += 1 def populateProjects(self): row = 0 for project in getProjects(): projectitem = QStandardItem(project.name) projectitem.setCheckable(True) self.projectsmodel.insertRow(row, projectitem) row += 1
class SetupDialog(QDialog, Ui_SetupDialog): """ Function and Event handling class for the Ui_SetupDialog. """ def __init__(self, parent): QDialog.__init__(self, parent) self._gui_logger = GUILogger("GUILogger", logging.INFO) self._gui_job = None EventLogger.add_logger(self._gui_logger) # FIXME better way to find interval and uids in tree_widget?! self.__tree_interval_tooltip = "Update interval in seconds" self.__tree_uid_tooltip = "UID cannot be empty" self.data_logger_thread = None self.tab_debug_warning = False self.device_dialog = None self.host_infos = None self.last_host = None self.host_index_changing = None self.setupUi(self) self.model_data = QStandardItemModel(self) self.model_data.setHorizontalHeaderLabels(['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit']) self.table_data.setModel(self.model_data) self.table_data.setColumnWidth(0, 160) self.table_data.setColumnWidth(1, 170) self.table_data.setColumnWidth(2, 50) self.table_data.setColumnWidth(3, 110) self.table_data.setColumnWidth(4, 70) self.table_data.setColumnWidth(5, 100) self.model_devices = QStandardItemModel(self) self.model_devices.setHorizontalHeaderLabels(['Device', 'Value']) self.tree_devices.setModel(self.model_devices) self.tree_devices.setColumnWidth(0, 300) self.widget_initialization() self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png'))) timestamp = int(time.time()) self.edit_csv_file_name.setText(os.path.join(get_home_path(), 'logger_data_{0}.csv'.format(timestamp))) self.edit_log_file_name.setText(os.path.join(get_home_path(), 'logger_debug_{0}.log'.format(timestamp))) self.combo_data_time_format.addItem(utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_data_time_format.addItem(utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_data_time_format.addItem(utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_data_time_format.addItem(utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_debug_time_format.addItem(utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_debug_time_format.addItem(utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_debug_time_format.addItem(utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_debug_time_format.addItem(utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_log_level.addItem('Debug', 'debug') self.combo_log_level.addItem('Info', 'info') self.combo_log_level.addItem('Warning', 'warning') self.combo_log_level.addItem('Error', 'error') self.combo_log_level.addItem('Critical', 'critical') self.combo_log_level.setCurrentIndex(0) # debug self.combo_debug_level.addItem('Debug', logging.DEBUG) self.combo_debug_level.addItem('Info', logging.INFO) self.combo_debug_level.addItem('Warning', logging.WARNING) self.combo_debug_level.addItem('Error', logging.ERROR) self.combo_debug_level.addItem('Critical', logging.CRITICAL) self.combo_debug_level.setCurrentIndex(1) # info self.update_ui_state() def update_ui_state(self): data_to_csv_file = self.check_data_to_csv_file.isChecked() debug_to_log_file = self.check_debug_to_log_file.isChecked() self.label_csv_file_name.setVisible(data_to_csv_file) self.edit_csv_file_name.setVisible(data_to_csv_file) self.btn_browse_csv_file_name.setVisible(data_to_csv_file) self.label_log_file_name.setVisible(debug_to_log_file) self.edit_log_file_name.setVisible(debug_to_log_file) self.btn_browse_log_file_name.setVisible(debug_to_log_file) self.label_log_level.setVisible(debug_to_log_file) self.combo_log_level.setVisible(debug_to_log_file) def widget_initialization(self): """ Sets default values for some widgets """ # Login data self.host_info_initialization() self.signal_initialization() def signal_initialization(self): """ Init of all important Signals and connections. """ # Buttons self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked) self.btn_save_config.clicked.connect(self.btn_save_config_clicked) self.btn_load_config.clicked.connect(self.btn_load_config_clicked) self.check_data_to_csv_file.stateChanged.connect(self.update_ui_state) self.check_debug_to_log_file.stateChanged.connect(self.update_ui_state) self.btn_browse_csv_file_name.clicked.connect(self.btn_browse_csv_file_name_clicked) self.btn_browse_log_file_name.clicked.connect(self.btn_browse_log_file_name_clicked) self.btn_clear_debug.clicked.connect(self.btn_clear_debug_clicked) self.combo_debug_level.currentIndexChanged.connect(self.combo_debug_level_changed) self.btn_add_device.clicked.connect(self.btn_add_device_clicked) self.btn_remove_device.clicked.connect(self.btn_remove_device_clicked) self.btn_remove_all_devices.clicked.connect(self.btn_remove_all_devices_clicked) self.tab_widget.currentChanged.connect(self.tab_reset_warning) self.btn_clear_data.clicked.connect(self.btn_clear_data_clicked) self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE), self.add_debug_message) self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE_TAB_HIGHLIGHT), self.highlight_debug_tab) self.combo_host.currentIndexChanged.connect(self._host_index_changed) self.spin_port.valueChanged.connect(self._port_changed) def host_info_initialization(self): """ initialize host by getting information out of brickv.config """ self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT) self.host_index_changing = True for host_info in self.host_infos: self.combo_host.addItem(host_info.host) self.last_host = None self.combo_host.setCurrentIndex(0) self.spin_port.setValue(self.host_infos[0].port) self.host_index_changing = False def btn_start_logging_clicked(self): """ Start/Stop of the logging process """ if (self.data_logger_thread is not None) and (not self.data_logger_thread.stopped): self.btn_start_logging.clicked.disconnect() self.data_logger_thread.stop() self._reset_stop() elif self.data_logger_thread is None: from brickv.data_logger import main self._gui_job = GuiDataJob(name="GuiData-Writer") self.connect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = main.main(None, GuiConfigHandler.create_config(self), self._gui_job) if self.data_logger_thread is not None: self.btn_start_logging.setText("Stop Logging") self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/stop-icon.png'))) self.tab_devices.setEnabled(False) self.tab_setup.setEnabled(False) self.tab_widget.setCurrentIndex(self.tab_widget.indexOf(self.tab_data)) self.tab_reset_warning() def _reset_stop(self): self.tab_devices.setEnabled(True) self.tab_setup.setEnabled(True) self.btn_start_logging.setText("Start Logging") self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png'))) self.disconnect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = None self._gui_job = None self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked) def btn_save_config_clicked(self): filename = get_save_file_name(get_main_window(), 'Save Config', get_home_path(), 'JSON Files (*.json)') if len(filename) == 0: return if not filename.lower().endswith('.json'): filename += '.json' config = GuiConfigHandler.create_config(self) if not save_config(config, filename): QMessageBox.warning(get_main_window(), 'Save Config', 'Could not save config to file! See Debug tab for details.', QMessageBox.Ok) def btn_load_config_clicked(self): filename = get_open_file_name(get_main_window(), 'Load Config', get_home_path(), 'JSON Files (*.json)') if len(filename) == 0: return config = load_and_validate_config(filename) if config == None: QMessageBox.warning(get_main_window(), 'Load Config', 'Could not load config from file! See Debug tab for details.', QMessageBox.Ok) return self.update_setup_tab(config) self.update_devices_tab(config) def btn_browse_csv_file_name_clicked(self): if len(self.edit_csv_file_name.text()) > 0: last_dir = os.path.dirname(os.path.realpath(self.edit_csv_file_name.text())) else: last_dir = get_home_path() filename = get_save_file_name(get_main_window(), 'Choose CSV File', last_dir, "CSV Files (*.csv)") if len(filename) > 0: if not filename.lower().endswith('.csv'): filename += '.csv' self.edit_csv_file_name.setText(filename) def btn_browse_log_file_name_clicked(self): if len(self.edit_log_file_name.text()) > 0: last_dir = os.path.dirname(os.path.realpath(self.edit_log_file_name.text())) else: last_dir = get_home_path() filename = get_save_file_name(get_main_window(), 'Choose Log File', last_dir, "Log Files (*.log)") if len(filename) > 0: if not filename.lower().endswith('.log'): filename += '.log' self.edit_log_file_name.setText(filename) def btn_add_device_clicked(self): """ Opens the DeviceDialog in Add-Mode. """ if self.device_dialog is None: self.device_dialog = DeviceDialog(self) self.device_dialog.btn_refresh_clicked() self.device_dialog.show() def btn_remove_device_clicked(self): selection = self.tree_devices.selectionModel().selectedIndexes() while len(selection) > 0: index = selection[0] while index.parent() != self.model_devices.invisibleRootItem().index(): index = index.parent() self.model_devices.removeRows(index.row(), 1) # get new selection, because row removal might invalid indices selection = self.tree_devices.selectionModel().selectedIndexes() def btn_remove_all_devices_clicked(self): self.model_devices.removeRows(0, self.model_devices.rowCount()) def btn_clear_data_clicked(self): self.model_data.removeRows(0, self.model_data.rowCount()) def tab_reset_warning(self): """ Resets the Warning @ the debug tab. """ if not self.tab_debug_warning or self.tab_widget.currentWidget().objectName() != self.tab_debug.objectName(): return self.tab_debug_warning = False self.tab_set(self.tab_widget.indexOf(self.tab_debug), self.palette().color(QPalette.WindowText), None) def combo_debug_level_changed(self): """ Changes the log level dynamically. """ self._gui_logger.level = self.combo_debug_level.itemData(self.combo_debug_level.currentIndex()) def tab_set(self, tab_index, color, icon=None): """ Sets the font Color and an icon, if given, at a specific tab. """ from PyQt4.QtGui import QIcon self.tab_widget.tabBar().setTabTextColor(tab_index, color) if icon is not None: self.tab_widget.setTabIcon(tab_index, QIcon(icon)) else: self.tab_widget.setTabIcon(tab_index, QIcon()) def _host_index_changed(self, i): """ Persists host information changes like in brickv.mainwindow Changes port if the host was changed """ if i < 0: return self.host_index_changing = True self.spin_port.setValue(self.host_infos[i].port) self.host_index_changing = False def _port_changed(self, value): """ Persists host information changes like in brickv.mainwindow """ if self.host_index_changing: return i = self.combo_host.currentIndex() if i < 0: return self.host_infos[i].port = self.spin_port.value() def update_setup_tab(self, config): EventLogger.debug('Updating setup tab from config') self.combo_host.setEditText(config['hosts']['default']['name']) self.spin_port.setValue(config['hosts']['default']['port']) self.combo_data_time_format.setCurrentIndex(max(self.combo_data_time_format.findData(config['data']['time_format']), 0)) self.check_data_to_csv_file.setChecked(config['data']['csv']['enabled']) self.edit_csv_file_name.setText(config['data']['csv']['file_name'].decode('utf-8')) self.combo_debug_time_format.setCurrentIndex(max(self.combo_debug_time_format.findData(config['debug']['time_format']), 0)) self.check_debug_to_log_file.setChecked(config['debug']['log']['enabled']) self.edit_log_file_name.setText(config['debug']['log']['file_name'].decode('utf-8')) self.combo_log_level.setCurrentIndex(max(self.combo_debug_time_format.findData(config['debug']['log']['level']), 0)) def update_devices_tab(self, config): EventLogger.debug('Updating devices tab from config') self.model_devices.removeRows(0, self.model_data.rowCount()) for device in config['devices']: self.add_device_to_tree(device) def add_device_to_tree(self, device): # check if device is already added if len(device['uid']) > 0: for row in range(self.model_devices.rowCount()): existing_name = self.model_devices.item(row, 0).text() exisitng_uid = self.tree_devices.indexWidget(self.model_devices.item(row, 1).index()).text() if device['name'] == existing_name and device['uid'] == exisitng_uid: EventLogger.info('Ignoring duplicate device "{0}" with UID "{1}"' .format(device['name'], device['uid'])) return # add device name_item = QStandardItem(device['name']) uid_item = QStandardItem('') self.model_devices.appendRow([name_item, uid_item]) edit_uid = QLineEdit() edit_uid.setPlaceholderText('Enter UID') edit_uid.setValidator(QRegExpValidator(QRegExp('^[{0}]{{1,6}}$'.format(BASE58)))) # FIXME: use stricter logic edit_uid.setText(device['uid']) self.tree_devices.setIndexWidget(uid_item.index(), edit_uid) value_specs = device_specs[device['name']]['values'] parent_item = QStandardItem('Values') name_item.appendRow([parent_item, QStandardItem('')]) self.tree_devices.expand(parent_item.index()) # add values for value_spec in value_specs: value_name_item = QStandardItem(value_spec['name']) value_interval_item = QStandardItem('') parent_item.appendRow([value_name_item, value_interval_item]) spinbox_interval = QSpinBox() spinbox_interval.setRange(0, (1 << 31) - 1) spinbox_interval.setSingleStep(1) spinbox_interval.setValue(device['values'][value_spec['name']]['interval']) spinbox_interval.setSuffix(' seconds') self.tree_devices.setIndexWidget(value_interval_item.index(), spinbox_interval) if value_spec['subvalues'] != None: for subvalue_name in value_spec['subvalues']: subvalue_name_item = QStandardItem(subvalue_name) subvalue_check_item = QStandardItem('') value_name_item.appendRow([subvalue_name_item, subvalue_check_item]) check_subvalue = QCheckBox() check_subvalue.setChecked(device['values'][value_spec['name']]['subvalues'][subvalue_name]) self.tree_devices.setIndexWidget(subvalue_check_item.index(), check_subvalue) self.tree_devices.expand(name_item.index()) # add options option_specs = device_specs[device['name']]['options'] if option_specs != None: parent_item = QStandardItem('Options') name_item.appendRow([parent_item, QStandardItem('')]) for option_spec in option_specs: option_name_item = QStandardItem(option_spec['name']) option_widget_item = QStandardItem('') parent_item.appendRow([option_name_item, option_widget_item]) if option_spec['type'] == 'choice': widget_option_value = QComboBox() for option_value_spec in option_spec['values']: widget_option_value.addItem(option_value_spec[0].decode('utf-8'), option_value_spec[1]) widget_option_value.setCurrentIndex(widget_option_value.findText(device['options'][option_spec['name']]['value'].decode('utf-8'))) elif option_spec['type'] == 'int': widget_option_value = QSpinBox() widget_option_value.setRange(option_spec['minimum'], option_spec['maximum']) widget_option_value.setSuffix(option_spec['suffix']) widget_option_value.setValue(device['options'][option_spec['name']]['value']) elif option_spec['type'] == 'bool': widget_option_value = QCheckBox() widget_option_value.setChecked(device['options'][option_spec['name']]['value']) self.tree_devices.setIndexWidget(option_widget_item.index(), widget_option_value) def add_debug_message(self, message): self.text_debug.append(message) while self.text_debug.document().blockCount() > 1000: cursor = QTextCursor(self.text_debug.document().begin()) cursor.select(QTextCursor.BlockUnderCursor) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) cursor.removeSelectedText() if self.checkbox_debug_auto_scroll.isChecked(): self.text_debug.verticalScrollBar().setValue(self.text_debug.verticalScrollBar().maximum()) def btn_clear_debug_clicked(self): self.text_debug.clear() def highlight_debug_tab(self): """ SIGNAL function: Highlight the debug tab when an error occurs. """ if not self.tab_debug_warning and self.tab_widget.currentWidget().objectName() != self.tab_debug.objectName(): self.tab_debug_warning = True self.tab_set(self.tab_widget.indexOf(self.tab_debug), QColor(255, 0, 0), os.path.join(get_resources_path(), "warning-icon.png")) def table_add_row(self, csv_data): """ SIGNAL function: Adds new CSV Data into the Table. """ rows = self.model_data.rowCount() while rows >= 1000: self.model_data.removeRow(0) rows = self.model_data.rowCount() row_number = None if rows > 0: try: row_number = int(self.model_data.headerData(rows - 1, Qt.Vertical)) except ValueError: pass self.model_data.appendRow([QStandardItem(csv_data.timestamp), QStandardItem(csv_data.name), QStandardItem(csv_data.uid), QStandardItem(csv_data.var_name), QStandardItem(str(csv_data.raw_data)), QStandardItem(csv_data.var_unit.decode('utf-8'))]) if row_number != None: self.model_data.setHeaderData(rows, Qt.Vertical, str(row_number + 1)) if self.checkbox_data_auto_scroll.isChecked(): self.table_data.scrollToBottom()
class MainWindow(mainwindow_widget, mainwindow_base): """ Main application window """ def __init__(self, settings): super(MainWindow, self).__init__() self.setupUi(self) self.settings = settings roam.featureform.settings = settings.settings self.canvaslayers = [] self.layerbuttons = [] self.project = None self.selectionbands = defaultdict(partial(QgsRubberBand, self.canvas)) self.canvas.setCanvasColor(Qt.white) self.canvas.enableAntiAliasing(True) self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor) self.bar = roam.messagebaritems.MessageBar(self) self.actionMap.setVisible(False) pal = QgsPalLabeling() self.canvas.mapRenderer().setLabelingEngine(pal) self.canvas.setFrameStyle(QFrame.NoFrame) self.menuGroup = QActionGroup(self) self.menuGroup.setExclusive(True) self.menuGroup.addAction(self.actionMap) self.menuGroup.addAction(self.actionDataEntry) self.menuGroup.addAction(self.actionProject) self.menuGroup.addAction(self.actionSync) self.menuGroup.addAction(self.actionSettings) self.menuGroup.triggered.connect(self.updatePage) self.editgroup = QActionGroup(self) self.editgroup.setExclusive(True) self.editgroup.addAction(self.actionPan) self.editgroup.addAction(self.actionZoom_In) self.editgroup.addAction(self.actionZoom_Out) self.editgroup.addAction(self.actionInfo) #TODO Extract GPS out into a service and remove UI stuff self.actionGPS = GPSAction(":/icons/gps", self.canvas, self.settings, self) self.projecttoolbar.addAction(self.actionGPS) self.projectwidget = ProjectsWidget(self) self.projectwidget.requestOpenProject.connect(self.loadProject) QgsProject.instance().readProject.connect(self._readProject) self.project_page.layout().addWidget(self.projectwidget) self.syncwidget = SyncWidget() self.syncpage.layout().addWidget(self.syncwidget) self.settingswidget = SettingsWidget(settings, self) self.settings_page.layout().addWidget(self.settingswidget) self.actionSettings.toggled.connect(self.settingswidget.populateControls) self.actionSettings.toggled.connect(self.settingswidget.readSettings) self.settingswidget.settingsupdated.connect(self.settingsupdated) self.dataentrywidget = DataEntryWidget(self.canvas, self.bar) self.widgetpage.layout().addWidget(self.dataentrywidget) self.dataentrywidget.rejected.connect(self.formrejected) self.dataentrywidget.featuresaved.connect(self.featureSaved) self.dataentrywidget.featuredeleted.connect(self.featuredeleted) self.dataentrywidget.failedsave.connect(self.failSave) self.dataentrywidget.helprequest.connect(self.showhelp) self.dataentrywidget.openimage.connect(self.openimage) def createSpacer(width=0, height=0): widget = QWidget() widget.setMinimumWidth(width) widget.setMinimumHeight(height) return widget gpsspacewidget = createSpacer(30) sidespacewidget = createSpacer(30) sidespacewidget2 = createSpacer(height=20) sidespacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sidespacewidget2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) gpsspacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.topspaceraction = self.projecttoolbar.insertWidget(self.actionGPS, gpsspacewidget) def createlabel(text): style = """ QLabel { color: #706565; font: 14px "Calibri" ; }""" label = QLabel(text) label.setStyleSheet(style) return label self.projectlabel = createlabel("Project: {project}") self.userlabel = createlabel("User: {user}".format(user=getpass.getuser())) self.positionlabel = createlabel('') self.statusbar.addWidget(self.projectlabel) self.statusbar.addWidget(self.userlabel) spacer = createSpacer() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.statusbar.addWidget(spacer) self.statusbar.addWidget(self.positionlabel) self.menutoolbar.insertWidget(self.actionQuit, sidespacewidget2) self.menutoolbar.insertWidget(self.actionProject, sidespacewidget) self.stackedWidget.currentChanged.connect(self.updateUIState) self.panels = [] self.connectButtons() self.band = QgsRubberBand(self.canvas) self.band.setIconSize(20) self.band.setWidth(10) self.band.setColor(QColor(186, 93, 212, 76)) self.canvas_page.layout().insertWidget(0, self.projecttoolbar) self.dataentrymodel = QStandardItemModel(self) self.dataentrycombo = QComboBox(self.projecttoolbar) self.dataentrycombo.setIconSize(QSize(48,48)) self.dataentrycombo.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.dataentrycombo.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.dataentrycombo.setModel(self.dataentrymodel) self.dataentrycomboaction = self.projecttoolbar.insertWidget(self.topspaceraction, self.dataentrycombo) self.dataentrycombo.showPopup = self.selectdataentry self.biglist = BigList(self.canvas) self.biglist.setlabel("Select data entry form") self.biglist.setmodel(self.dataentrymodel) self.biglist.itemselected.connect(self.dataentrychanged) self.biglist.hide() self.centralwidget.layout().addWidget(self.statusbar) self.actionGPSFeature.setProperty('dataentry', True) self.infodock = InfoDock(self.canvas) self.infodock.requestopenform.connect(self.openForm) self.infodock.featureupdated.connect(self.highlightfeature) self.infodock.resultscleared.connect(self.clearselection) self.infodock.openurl.connect(self.viewurl) self.infodock.hide() self.hidedataentry() self.canvas.extentsChanged.connect(self.updatestatuslabel) self.projecttoolbar.toolButtonStyleChanged.connect(self.updatecombo) def selectdataentry(self, ): if self.dataentrycombo.count() == 0: return self.biglist.show() def viewurl(self, url): """ Open a URL in Roam :param url: :return: """ key = url.toString().lstrip('file://') try: # Hack. Eww fix me. data, imagetype = roam.htmlviewer.images[os.path.basename(key)] except KeyError: # It's not a image so lets just pass it of as a normal # URL QDesktopServices.openUrl(url) return pix = QPixmap() if imagetype == 'base64': pix.loadFromData(data) else: pix.load(data) self.openimage(pix) def openimage(self, pixmap): viewer = ImageViewer(self.stackedWidget) viewer.resize(self.stackedWidget.size()) viewer.openimage(pixmap) def updatecombo(self, *args): self.dataentrycombo.setMinimumHeight(0) def settingsupdated(self, settings): settings.save() self.show() self.actionGPS.updateGPSPort() # eww! roam.featureform.settings = settings.settings def updatestatuslabel(self): extent = self.canvas.extent() self.positionlabel.setText("Map Center: {}".format(extent.center().toString())) def highlightselection(self, results): for layer, features in results.iteritems(): band = self.selectionbands[layer] band.setColor(QColor(255, 0, 0, 150)) band.setIconSize(20) band.setWidth(2) band.setBrushStyle(Qt.NoBrush) band.reset(layer.geometryType()) for feature in features: band.addGeometry(feature.geometry(), layer) def clearselection(self): # Clear the main selection rubber band self.band.reset() # Clear the rest for band in self.selectionbands.itervalues(): band.reset() def highlightfeature(self, layer, feature, features): self.clearselection() self.highlightselection({layer: features}) self.band.setToGeometry(feature.geometry(), layer) def showmap(self): self.actionMap.setVisible(True) self.actionMap.trigger() def hidedataentry(self): self.actionDataEntry.setVisible(False) def showdataentry(self): self.actionDataEntry.setVisible(True) self.actionDataEntry.trigger() def dataentrychanged(self, index): wasactive = self.clearCapatureTools() if not index.isValid(): return modelindex = index # modelindex = self.dataentrymodel.index(index, 0) form = modelindex.data(Qt.UserRole + 1) self.dataentrycombo.setCurrentIndex(index.row()) self.createCaptureButtons(form, wasactive) def raiseerror(self, *exinfo): info = traceback.format_exception(*exinfo) item = self.bar.pushError('Seems something has gone wrong. Press for more details', info) def setMapTool(self, tool, *args): self.canvas.setMapTool(tool) def homeview(self): """ Zoom the mapview canvas to the extents the project was opened at i.e. the default extent. """ self.canvas.setExtent(self.defaultextent) self.canvas.refresh() def connectButtons(self): def connectAction(action, tool): action.toggled.connect(partial(self.setMapTool, tool)) def cursor(name): pix = QPixmap(name) pix = pix.scaled(QSize(24,24)) return QCursor(pix) self.zoomInTool = QgsMapToolZoom(self.canvas, False) self.zoomOutTool = QgsMapToolZoom(self.canvas, True) self.panTool = TouchMapTool(self.canvas) self.moveTool = MoveTool(self.canvas, []) self.infoTool = InfoTool(self.canvas) connectAction(self.actionZoom_In, self.zoomInTool) connectAction(self.actionZoom_Out, self.zoomOutTool) connectAction(self.actionPan, self.panTool) connectAction(self.actionMove, self.moveTool) connectAction(self.actionInfo, self.infoTool) self.zoomInTool.setCursor(cursor(':/icons/in')) self.zoomOutTool.setCursor(cursor(':/icons/out')) self.infoTool.setCursor(cursor(':/icons/info')) self.actionRaster.triggered.connect(self.toggleRasterLayers) self.infoTool.infoResults.connect(self.showInfoResults) # The edit toolbutton is currently not being used but leaving it for feature. self.moveTool.layersupdated.connect(self.actionMove.setEnabled) self.moveTool.layersupdated.connect(self.actionEdit_Tools.setEnabled) self.actionGPSFeature.triggered.connect(self.addFeatureAtGPS) self.actionGPSFeature.setEnabled(self.actionGPS.isConnected) self.actionGPS.gpsfixed.connect(self.actionGPSFeature.setEnabled) self.actionHome.triggered.connect(self.homeview) self.actionQuit.triggered.connect(self.exit) def showToolError(self, label, message): self.bar.pushMessage(label, message, QgsMessageBar.WARNING) def clearCapatureTools(self): captureselected = False for action in self.projecttoolbar.actions(): if action.objectName() == "capture" and action.isChecked(): captureselected = True if action.property('dataentry'): self.projecttoolbar.removeAction(action) return captureselected def createCaptureButtons(self, form, wasselected): tool = form.getMaptool()(self.canvas) for action in tool.actions: # Create the action here. if action.ismaptool: action.toggled.connect(partial(self.setMapTool, tool)) # Set the action as a data entry button so we can remove it later. action.setProperty("dataentry", True) self.editgroup.addAction(action) self.layerbuttons.append(action) self.projecttoolbar.insertAction(self.topspaceraction, action) if action.isdefault: action.setChecked(wasselected) if hasattr(tool, 'geometryComplete'): add = partial(self.addNewFeature, form) tool.geometryComplete.connect(add) else: tool.finished.connect(self.openForm) tool.error.connect(partial(self.showToolError, form.label)) self.projecttoolbar.insertAction(self.topspaceraction, self.actionGPSFeature) self.actionGPSFeature.setVisible(not tool.isEditTool()) def createFormButtons(self, forms): """ Create buttons for each form that is defined """ self.dataentrymodel.clear() self.clearCapatureTools() def captureFeature(form): item = QStandardItem(QIcon(form.icon), form.icontext) item.setData(form, Qt.UserRole + 1) item.setSizeHint(QSize(item.sizeHint().width(), self.projecttoolbar.height())) self.dataentrymodel.appendRow(item) capabilitityhandlers = {"capture": captureFeature} failedforms = [] for form in forms: valid, reasons = form.valid if not valid: roam.utils.log("Form is invalid for data entry because {}".format(reasons)) failedforms.append((form, reasons)) continue for capability in form.capabilities: try: capabilitityhandlers[capability](form) except KeyError: # Just ignore capabilities we don't support yet. continue if failedforms: for form, reasons in failedforms: html = "<h3>{}</h3><br>{}".format(form.label, "<br>".join(reasons)) self.bar.pushMessage("Form errors", "Looks like some forms couldn't be loaded", level=QgsMessageBar.WARNING, extrainfo=html) visible = self.dataentrymodel.rowCount() > 0 self.dataentrycomboaction.setVisible(visible) self.dataentrycombo.setMinimumHeight(self.projecttoolbar.height()) index = self.dataentrymodel.index(0, 0) self.dataentrychanged(index) def addFeatureAtGPS(self): """ Add a record at the current GPS location. """ index = self.dataentrycombo.currentIndex() modelindex = self.dataentrymodel.index(index, 0) form = modelindex.data(Qt.UserRole + 1) point = self.actionGPS.position point = QgsGeometry.fromPoint(point) self.addNewFeature(form=form, geometry=point) def clearToolRubberBand(self): """ Clear the rubber band of the active tool if it has one """ tool = self.canvas.mapTool() try: tool.clearBand() except AttributeError: # No clearBand method found, but that's cool. pass def showhelp(self, url): help = HelpPage(self.stackedWidget) help.setHelpPage(url) help.show() def dataentryfinished(self): self.hidedataentry() self.showmap() self.cleartempobjects() self.infodock.refreshcurrent() def featuredeleted(self): self.dataentryfinished() self.bar.pushMessage("Deleted", "Feature Deleted", QgsMessageBar.INFO, 1) self.canvas.refresh() def featureSaved(self): self.dataentryfinished() self.canvas.refresh() def failSave(self, messages): self.bar.pushError("Error when saving changes.", messages) def cleartempobjects(self): self.band.reset() self.clearToolRubberBand() def formrejected(self, message, level): self.dataentryfinished() if message: self.bar.pushMessage("Form Message", message, level, duration=2) self.cleartempobjects() def openForm(self, form, feature): """ Open the form that is assigned to the layer """ self.band.setToGeometry(feature.geometry(), form.QGISLayer) self.showdataentry() self.dataentrywidget.openform(feature=feature, form=form, project=self.project) def addNewFeature(self, form, geometry): """ Add a new new feature to the given layer """ layer = form.QGISLayer fields = layer.pendingFields() feature = QgsFeature(fields) feature.setGeometry(geometry) for index in xrange(fields.count()): pkindexes = layer.dataProvider().pkAttributeIndexes() if index in pkindexes and layer.dataProvider().name() == 'spatialite': continue value = layer.dataProvider().defaultValue(index) feature[index] = value self.openForm(form, feature) def exit(self): """ Exit the application. """ QApplication.exit(0) def showInfoResults(self, results): self.infodock.clearResults() forms = {} for layer in results.keys(): layername = layer.name() if not layername in forms: forms[layername] = list(self.project.formsforlayer(layername)) self.infodock.setResults(results, forms) self.infodock.show() def toggleRasterLayers(self): """ Toggle all raster layers on or off. """ if not self.canvaslayers: return #Freeze the canvas to save on UI refresh self.canvas.freeze() for layer in self.canvaslayers: if layer.layer().type() == QgsMapLayer.RasterLayer: layer.setVisible(not layer.isVisible()) # Really!? We have to reload the whole layer set every time? # WAT? self.canvas.setLayerSet(self.canvaslayers) self.canvas.freeze(False) self.canvas.refresh() def missingLayers(self, layers): """ Called when layers have failed to load from the current project """ roam.utils.warning("Missing layers") map(roam.utils.warning, layers) missinglayers = roam.messagebaritems.MissingLayerItem(layers, parent=self.bar) self.bar.pushItem(missinglayers) def loadprojects(self, projects): """ Load the given projects into the project list """ projects = list(projects) self.projectwidget.loadProjectList(projects) self.syncwidget.loadprojects(projects) def updatePage(self, action): """ Update the current stack page based on the current selected action """ page = action.property("page") self.stackedWidget.setCurrentIndex(page) def show(self): """ Override show method. Handles showing the app in fullscreen mode or just maximized """ fullscreen = self.settings.settings.get("fullscreen", False) if fullscreen: self.showFullScreen() else: self.showMaximized() def viewprojects(self): self.stackedWidget.setCurrentIndex(1) def updateUIState(self, page): """ Update the UI state to reflect the currently selected page in the stacked widget """ pass @roam.utils.timeit def _readProject(self, doc): """ readProject is called by QgsProject once the map layer has been populated with all the layers """ parser = ProjectParser(doc) canvasnode = parser.canvasnode self.canvas.freeze() self.canvas.mapRenderer().readXML(canvasnode) self.canvaslayers = parser.canvaslayers() self.canvas.setLayerSet(self.canvaslayers) self.canvas.updateScale() self.projectOpened() self.canvas.freeze(False) self.canvas.refresh() self.showmap() @roam.utils.timeit def projectOpened(self): """ Called when a new project is opened in QGIS. """ projectpath = QgsProject.instance().fileName() self.project = Project.from_folder(os.path.dirname(projectpath)) self.projectlabel.setText("Project: {}".format(self.project.name)) self.createFormButtons(forms=self.project.forms) # Enable the raster layers button only if the project contains a raster layer. layers = QgsMapLayerRegistry.instance().mapLayers().values() hasrasters = any(layer.type() == QgsMapLayer.RasterLayer for layer in layers) self.actionRaster.setEnabled(hasrasters) self.defaultextent = self.canvas.extent() roam.utils.info("Extent: {}".format(self.defaultextent.toString())) # Show panels for panel in self.project.getPanels(): self.mainwindow.addDockWidget(Qt.BottomDockWidgetArea, panel) self.panels.append(panel) # TODO Abstract this out if not self.project.selectlayers: selectionlayers = QgsMapLayerRegistry.instance().mapLayers().values() else: selectionlayers = [] for layername in self.project.selectlayers: try: layer = QgsMapLayerRegistry.instance().mapLayersByName(layername)[0] except IndexError: roam.utils.warning("Can't find QGIS layer for select layer {}".format(layername)) continue selectionlayers.append(layer) self.infoTool.selectionlayers = selectionlayers self.actionPan.trigger() #noinspection PyArgumentList @roam.utils.timeit def loadProject(self, project): """ Load a project into the application . """ roam.utils.log(project) roam.utils.log(project.name) roam.utils.log(project.projectfile) roam.utils.log(project.valid) (passed, message) = project.onProjectLoad() if not passed: self.bar.pushMessage("Project load rejected", "Sorry this project couldn't" "be loaded. Click for me details.", QgsMessageBar.WARNING, extrainfo=message) return self.actionMap.trigger() self.closeProject() self.canvas.refresh() self.canvas.repaint() self.infodock.clearResults() # No idea why we have to set this each time. Maybe QGIS deletes it for # some reason. self.badLayerHandler = BadLayerHandler(callback=self.missingLayers) QgsProject.instance().setBadLayerHandler(self.badLayerHandler) self.stackedWidget.setCurrentIndex(3) self.projectloading_label.setText("Project {} Loading".format(project.name)) pixmap = QPixmap(project.splash) w = self.projectimage.width() h = self.projectimage.height() self.projectimage.setPixmap(pixmap.scaled(w,h, Qt.KeepAspectRatio)) QApplication.processEvents() QDir.setCurrent(os.path.dirname(project.projectfile)) fileinfo = QFileInfo(project.projectfile) QgsProject.instance().read(fileinfo) def closeProject(self): """ Close the current open project """ self.canvas.freeze() QgsMapLayerRegistry.instance().removeAllMapLayers() self.canvas.clear() self.canvas.freeze(False) for panel in self.panels: self.removeDockWidget(panel) del panel # Remove all the old buttons for action in self.layerbuttons: self.editgroup.removeAction(action) self.dataentrymodel.clear() self.panels = [] self.project = None self.dataentrywidget.clear() self.hidedataentry() self.infodock.close()
class SetupDialog(QDialog, Ui_SetupDialog): """ Function and Event handling class for the Ui_SetupDialog. """ def __init__(self, parent): QDialog.__init__(self, parent) self._gui_logger = GUILogger("GUILogger", logging.INFO) self._gui_job = None EventLogger.add_logger(self._gui_logger) # FIXME better way to find interval and uids in tree_widget?! self.__tree_interval_tooltip = "Update interval in seconds" self.__tree_uid_tooltip = "UID cannot be empty" self.data_logger_thread = None self.tab_debug_warning = False self.device_dialog = None self.host_infos = None self.last_host = None self.host_index_changing = None self.setupUi(self) self.model_data = QStandardItemModel(self) self.model_data.setHorizontalHeaderLabels( ['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit']) self.table_data.setModel(self.model_data) self.table_data.setColumnWidth(0, 160) self.table_data.setColumnWidth(1, 170) self.table_data.setColumnWidth(2, 50) self.table_data.setColumnWidth(3, 110) self.table_data.setColumnWidth(4, 70) self.table_data.setColumnWidth(5, 100) self.model_devices = QStandardItemModel(self) self.model_devices.setHorizontalHeaderLabels(['Device', 'Value']) self.tree_devices.setModel(self.model_devices) self.tree_devices.setColumnWidth(0, 300) self.widget_initialization() self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/start-icon.png'))) timestamp = int(time.time()) self.edit_csv_file_name.setText( os.path.join(get_home_path(), 'logger_data_{0}.csv'.format(timestamp))) self.edit_log_file_name.setText( os.path.join(get_home_path(), 'logger_debug_{0}.log'.format(timestamp))) self.combo_data_time_format.addItem( utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_data_time_format.addItem( utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_data_time_format.addItem( utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_data_time_format.addItem( utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_debug_time_format.addItem( utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_debug_time_format.addItem( utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_debug_time_format.addItem( utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_debug_time_format.addItem( utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_log_level.addItem('Debug', 'debug') self.combo_log_level.addItem('Info', 'info') self.combo_log_level.addItem('Warning', 'warning') self.combo_log_level.addItem('Error', 'error') self.combo_log_level.addItem('Critical', 'critical') self.combo_log_level.setCurrentIndex(0) # debug self.combo_debug_level.addItem('Debug', logging.DEBUG) self.combo_debug_level.addItem('Info', logging.INFO) self.combo_debug_level.addItem('Warning', logging.WARNING) self.combo_debug_level.addItem('Error', logging.ERROR) self.combo_debug_level.addItem('Critical', logging.CRITICAL) self.combo_debug_level.setCurrentIndex(1) # info self.update_ui_state() def update_ui_state(self): data_to_csv_file = self.check_data_to_csv_file.isChecked() debug_to_log_file = self.check_debug_to_log_file.isChecked() self.label_csv_file_name.setVisible(data_to_csv_file) self.edit_csv_file_name.setVisible(data_to_csv_file) self.btn_browse_csv_file_name.setVisible(data_to_csv_file) self.label_log_file_name.setVisible(debug_to_log_file) self.edit_log_file_name.setVisible(debug_to_log_file) self.btn_browse_log_file_name.setVisible(debug_to_log_file) self.label_log_level.setVisible(debug_to_log_file) self.combo_log_level.setVisible(debug_to_log_file) def widget_initialization(self): """ Sets default values for some widgets """ # Login data self.host_info_initialization() self.signal_initialization() def signal_initialization(self): """ Init of all important Signals and connections. """ # Buttons self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked) self.btn_save_config.clicked.connect(self.btn_save_config_clicked) self.btn_load_config.clicked.connect(self.btn_load_config_clicked) self.check_data_to_csv_file.stateChanged.connect(self.update_ui_state) self.check_debug_to_log_file.stateChanged.connect(self.update_ui_state) self.btn_browse_csv_file_name.clicked.connect( self.btn_browse_csv_file_name_clicked) self.btn_browse_log_file_name.clicked.connect( self.btn_browse_log_file_name_clicked) self.btn_clear_debug.clicked.connect(self.btn_clear_debug_clicked) self.combo_debug_level.currentIndexChanged.connect( self.combo_debug_level_changed) self.btn_add_device.clicked.connect(self.btn_add_device_clicked) self.btn_remove_device.clicked.connect(self.btn_remove_device_clicked) self.btn_remove_all_devices.clicked.connect( self.btn_remove_all_devices_clicked) self.tab_widget.currentChanged.connect(self.tab_reset_warning) self.btn_clear_data.clicked.connect(self.btn_clear_data_clicked) self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE), self.add_debug_message) self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE_TAB_HIGHLIGHT), self.highlight_debug_tab) self.combo_host.currentIndexChanged.connect(self._host_index_changed) self.spin_port.valueChanged.connect(self._port_changed) def host_info_initialization(self): """ initialize host by getting information out of brickv.config """ self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT) self.host_index_changing = True for host_info in self.host_infos: self.combo_host.addItem(host_info.host) self.last_host = None self.combo_host.setCurrentIndex(0) self.spin_port.setValue(self.host_infos[0].port) self.host_index_changing = False def btn_start_logging_clicked(self): """ Start/Stop of the logging process """ if (self.data_logger_thread is not None) and (not self.data_logger_thread.stopped): self.btn_start_logging.clicked.disconnect() self.data_logger_thread.stop() self._reset_stop() elif self.data_logger_thread is None: from brickv.data_logger import main self._gui_job = GuiDataJob(name="GuiData-Writer") self.connect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = main.main( None, GuiConfigHandler.create_config(self), self._gui_job) if self.data_logger_thread is not None: self.btn_start_logging.setText("Stop Logging") self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/stop-icon.png'))) self.tab_devices.setEnabled(False) self.tab_setup.setEnabled(False) self.tab_widget.setCurrentIndex( self.tab_widget.indexOf(self.tab_data)) self.tab_reset_warning() def _reset_stop(self): self.tab_devices.setEnabled(True) self.tab_setup.setEnabled(True) self.btn_start_logging.setText("Start Logging") self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/start-icon.png'))) self.disconnect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = None self._gui_job = None self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked) def btn_save_config_clicked(self): filename = get_save_file_name(get_main_window(), 'Save Config', get_home_path(), 'JSON Files (*.json)') if len(filename) == 0: return if not filename.lower().endswith('.json'): filename += '.json' config = GuiConfigHandler.create_config(self) if not save_config(config, filename): QMessageBox.warning( get_main_window(), 'Save Config', 'Could not save config to file! See Debug tab for details.', QMessageBox.Ok) def btn_load_config_clicked(self): filename = get_open_file_name(get_main_window(), 'Load Config', get_home_path(), 'JSON Files (*.json)') if len(filename) == 0: return config = load_and_validate_config(filename) if config == None: QMessageBox.warning( get_main_window(), 'Load Config', 'Could not load config from file! See Debug tab for details.', QMessageBox.Ok) return self.update_setup_tab(config) self.update_devices_tab(config) def btn_browse_csv_file_name_clicked(self): if len(self.edit_csv_file_name.text()) > 0: last_dir = os.path.dirname( os.path.realpath(self.edit_csv_file_name.text())) else: last_dir = get_home_path() filename = get_save_file_name(get_main_window(), 'Choose CSV File', last_dir, "CSV Files (*.csv)") if len(filename) > 0: if not filename.lower().endswith('.csv'): filename += '.csv' self.edit_csv_file_name.setText(filename) def btn_browse_log_file_name_clicked(self): if len(self.edit_log_file_name.text()) > 0: last_dir = os.path.dirname( os.path.realpath(self.edit_log_file_name.text())) else: last_dir = get_home_path() filename = get_save_file_name(get_main_window(), 'Choose Log File', last_dir, "Log Files (*.log)") if len(filename) > 0: if not filename.lower().endswith('.log'): filename += '.log' self.edit_log_file_name.setText(filename) def btn_add_device_clicked(self): """ Opens the DeviceDialog in Add-Mode. """ if self.device_dialog is None: self.device_dialog = DeviceDialog(self) self.device_dialog.btn_refresh_clicked() self.device_dialog.show() def btn_remove_device_clicked(self): selection = self.tree_devices.selectionModel().selectedIndexes() while len(selection) > 0: index = selection[0] while index.parent() != self.model_devices.invisibleRootItem( ).index(): index = index.parent() self.model_devices.removeRows(index.row(), 1) # get new selection, because row removal might invalid indices selection = self.tree_devices.selectionModel().selectedIndexes() def btn_remove_all_devices_clicked(self): self.model_devices.removeRows(0, self.model_devices.rowCount()) def btn_clear_data_clicked(self): self.model_data.removeRows(0, self.model_data.rowCount()) def tab_reset_warning(self): """ Resets the Warning @ the debug tab. """ if not self.tab_debug_warning or self.tab_widget.currentWidget( ).objectName() != self.tab_debug.objectName(): return self.tab_debug_warning = False self.tab_set(self.tab_widget.indexOf(self.tab_debug), self.palette().color(QPalette.WindowText), None) def combo_debug_level_changed(self): """ Changes the log level dynamically. """ self._gui_logger.level = self.combo_debug_level.itemData( self.combo_debug_level.currentIndex()) def tab_set(self, tab_index, color, icon=None): """ Sets the font Color and an icon, if given, at a specific tab. """ from PyQt4.QtGui import QIcon self.tab_widget.tabBar().setTabTextColor(tab_index, color) if icon is not None: self.tab_widget.setTabIcon(tab_index, QIcon(icon)) else: self.tab_widget.setTabIcon(tab_index, QIcon()) def _host_index_changed(self, i): """ Persists host information changes like in brickv.mainwindow Changes port if the host was changed """ if i < 0: return self.host_index_changing = True self.spin_port.setValue(self.host_infos[i].port) self.host_index_changing = False def _port_changed(self, value): """ Persists host information changes like in brickv.mainwindow """ if self.host_index_changing: return i = self.combo_host.currentIndex() if i < 0: return self.host_infos[i].port = self.spin_port.value() def update_setup_tab(self, config): EventLogger.debug('Updating setup tab from config') self.combo_host.setEditText(config['hosts']['default']['name']) self.spin_port.setValue(config['hosts']['default']['port']) self.combo_data_time_format.setCurrentIndex( max( self.combo_data_time_format.findData( config['data']['time_format']), 0)) self.check_data_to_csv_file.setChecked( config['data']['csv']['enabled']) self.edit_csv_file_name.setText( config['data']['csv']['file_name'].decode('utf-8')) self.combo_debug_time_format.setCurrentIndex( max( self.combo_debug_time_format.findData( config['debug']['time_format']), 0)) self.check_debug_to_log_file.setChecked( config['debug']['log']['enabled']) self.edit_log_file_name.setText( config['debug']['log']['file_name'].decode('utf-8')) self.combo_log_level.setCurrentIndex( max( self.combo_debug_time_format.findData( config['debug']['log']['level']), 0)) def update_devices_tab(self, config): EventLogger.debug('Updating devices tab from config') self.model_devices.removeRows(0, self.model_data.rowCount()) for device in config['devices']: self.add_device_to_tree(device) def add_device_to_tree(self, device): # check if device is already added if len(device['uid']) > 0: for row in range(self.model_devices.rowCount()): existing_name = self.model_devices.item(row, 0).text() exisitng_uid = self.tree_devices.indexWidget( self.model_devices.item(row, 1).index()).text() if device['name'] == existing_name and device[ 'uid'] == exisitng_uid: EventLogger.info( 'Ignoring duplicate device "{0}" with UID "{1}"'. format(device['name'], device['uid'])) return # add device name_item = QStandardItem(device['name']) uid_item = QStandardItem('') self.model_devices.appendRow([name_item, uid_item]) edit_uid = QLineEdit() edit_uid.setPlaceholderText('Enter UID') edit_uid.setValidator( QRegExpValidator(QRegExp( '^[{0}]{{1,6}}$'.format(BASE58)))) # FIXME: use stricter logic edit_uid.setText(device['uid']) self.tree_devices.setIndexWidget(uid_item.index(), edit_uid) value_specs = device_specs[device['name']]['values'] parent_item = QStandardItem('Values') name_item.appendRow([parent_item, QStandardItem('')]) self.tree_devices.expand(parent_item.index()) # add values for value_spec in value_specs: value_name_item = QStandardItem(value_spec['name']) value_interval_item = QStandardItem('') parent_item.appendRow([value_name_item, value_interval_item]) spinbox_interval = QSpinBox() spinbox_interval.setRange(0, (1 << 31) - 1) spinbox_interval.setSingleStep(1) spinbox_interval.setValue( device['values'][value_spec['name']]['interval']) spinbox_interval.setSuffix(' seconds') self.tree_devices.setIndexWidget(value_interval_item.index(), spinbox_interval) if value_spec['subvalues'] != None: for subvalue_name in value_spec['subvalues']: subvalue_name_item = QStandardItem(subvalue_name) subvalue_check_item = QStandardItem('') value_name_item.appendRow( [subvalue_name_item, subvalue_check_item]) check_subvalue = QCheckBox() check_subvalue.setChecked(device['values'][ value_spec['name']]['subvalues'][subvalue_name]) self.tree_devices.setIndexWidget( subvalue_check_item.index(), check_subvalue) self.tree_devices.expand(name_item.index()) # add options option_specs = device_specs[device['name']]['options'] if option_specs != None: parent_item = QStandardItem('Options') name_item.appendRow([parent_item, QStandardItem('')]) for option_spec in option_specs: option_name_item = QStandardItem(option_spec['name']) option_widget_item = QStandardItem('') parent_item.appendRow([option_name_item, option_widget_item]) if option_spec['type'] == 'choice': widget_option_value = QComboBox() for option_value_spec in option_spec['values']: widget_option_value.addItem( option_value_spec[0].decode('utf-8'), option_value_spec[1]) widget_option_value.setCurrentIndex( widget_option_value.findText(device['options'][ option_spec['name']]['value'].decode('utf-8'))) elif option_spec['type'] == 'int': widget_option_value = QSpinBox() widget_option_value.setRange(option_spec['minimum'], option_spec['maximum']) widget_option_value.setSuffix(option_spec['suffix']) widget_option_value.setValue( device['options'][option_spec['name']]['value']) elif option_spec['type'] == 'bool': widget_option_value = QCheckBox() widget_option_value.setChecked( device['options'][option_spec['name']]['value']) self.tree_devices.setIndexWidget(option_widget_item.index(), widget_option_value) def add_debug_message(self, message): self.text_debug.append(message) while self.text_debug.document().blockCount() > 1000: cursor = QTextCursor(self.text_debug.document().begin()) cursor.select(QTextCursor.BlockUnderCursor) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) cursor.removeSelectedText() if self.checkbox_debug_auto_scroll.isChecked(): self.text_debug.verticalScrollBar().setValue( self.text_debug.verticalScrollBar().maximum()) def btn_clear_debug_clicked(self): self.text_debug.clear() def highlight_debug_tab(self): """ SIGNAL function: Highlight the debug tab when an error occurs. """ if not self.tab_debug_warning and self.tab_widget.currentWidget( ).objectName() != self.tab_debug.objectName(): self.tab_debug_warning = True self.tab_set( self.tab_widget.indexOf(self.tab_debug), QColor(255, 0, 0), os.path.join(get_resources_path(), "warning-icon.png")) def table_add_row(self, csv_data): """ SIGNAL function: Adds new CSV Data into the Table. """ rows = self.model_data.rowCount() while rows >= 1000: self.model_data.removeRow(0) rows = self.model_data.rowCount() row_number = None if rows > 0: try: row_number = int( self.model_data.headerData(rows - 1, Qt.Vertical)) except ValueError: pass self.model_data.appendRow([ QStandardItem(csv_data.timestamp), QStandardItem(csv_data.name), QStandardItem(csv_data.uid), QStandardItem(csv_data.var_name), QStandardItem(str(csv_data.raw_data)), QStandardItem(csv_data.var_unit.decode('utf-8')) ]) if row_number != None: self.model_data.setHeaderData(rows, Qt.Vertical, str(row_number + 1)) if self.checkbox_data_auto_scroll.isChecked(): self.table_data.scrollToBottom()
class STRPartyListView(QListView): """ A widget for listing and selecting STR party entities. .. versionadded:: 1.5 """ party_selected = pyqtSignal(QStandardItem) party_deselected = pyqtSignal(QStandardItem) def __init__(self, parent=None, profile=None, social_tenure=None): super(STRPartyListView, self).__init__(parent) self._model = QStandardItemModel(self) self._model.setColumnCount(1) self.setModel(self._model) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self._model.itemChanged.connect(self._on_item_changed) self._profile = profile if not self._profile is None: self._load_profile_entities() self._social_tenure = social_tenure if not self._social_tenure is None: self.select_parties(self._social_tenure.parties) def _on_item_changed(self, item): # Emit signals when an item has been (de)selected. if item.checkState() == Qt.Checked: self.party_selected.emit(item) elif item.checkState() == Qt.Unchecked: self.party_deselected.emit(item) @property def profile(self): """ :return: Returns the current profile object in the configuration. :rtype: Profile """ return self._profile @profile.setter def profile(self, profile): """ Sets the current profile object in the configuration. :param profile: Profile object. :type profile: Profile """ self._profile = profile self._load_profile_entities() @property def social_tenure(self): """ :return: Returns the profile's social tenure entity. :rtype: SocialTenure """ return self._social_tenure @social_tenure.setter def social_tenure(self, social_tenure): """ Set the social_tenure entity. :param social_tenure: A profile's social tenure entity. :type social_tenure: SocialTenure """ self._social_tenure = social_tenure self.select_parties(self._social_tenure.parties) def _load_profile_entities(self): # Reset view self.clear() # Populate entity items in the view for e in self._profile.user_entities(): self._add_entity(e) def _add_entity(self, party): # Add entity item to view item = QStandardItem(QIcon(':/plugins/stdm/images/icons/table.png'), party.short_name) item.setCheckable(True) item.setCheckState(Qt.Unchecked) self._model.appendRow(item) def select_parties(self, parties): """ Checks party entities in the view and emit the party_selected signal for each item selected. :param parties: Collection of STR party entities. :type parties: list """ # Clear selection self.clear_selection() for p in parties: name = p.short_name self.select_party(name) def parties(self): """ :return: Returns a list of selected party names. :rtype: list """ selected_items = [] for i in range(self._model.rowCount()): item = self._model.item(i) if item.checkState() == Qt.Checked: selected_items.append(item.text()) return selected_items def clear(self): """ Remove all party items in the view. """ self._model.clear() self._model.setColumnCount(1) def clear_selection(self): """ Uncheck all items in the view. """ for i in range(self._model.rowCount()): item = self._model.item(i) if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked) def select_party(self, name): """ Selects a party entity with the given short name. :param name: Entity short name :type name: str """ items = self._model.findItems(name) if len(items) > 0: item = items[0] if item.checkState() == Qt.Unchecked: item.setCheckState(Qt.Checked) def deselect_party(self, name): """ Deselects a party entity with the given short name. :param name: Entity short name :type name: str """ items = self._model.findItems(name) if len(items) > 0: item = items[0] if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked)
class DefaultsDlg(QDialog, Ui_Dialog): """ Class documentation goes here. """ def __init__(self, defaults, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super().__init__(parent) self.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.defaults = defaults self.fillScalars() self.fillPlots() self.fillCalculations() def updateDefaults(self): self.defaults['defaultScalars'] = self.setDefaultScalars() self.defaults['defaultPlots'] = self.setDefaultPlots() self.defaults['defaultCalculations'] = self.setDefaultCalculations() def fillScalars(self): scalars = [ 'absorbance (%)', 'reflectance (%)', 'transmittance (%)', 'absorbance (mA/cm²)', 'reflectance (mA/cm²)', 'transmittance (mA/cm²)', 'generation', 'Jmax (mA/cm²)', 'absorption layerwise (%)', 'absorption layerwise (mA/cm²)', 'collection layerwise (%)', 'collection layerwise (mA/cm²)', 'calc. time (s)' ] self.scalarListModel = QStandardItemModel() scalarsToShow = self.defaults['defaultScalars'] for value in scalars: item = QStandardItem(value) check = Qt.Checked if value in scalarsToShow else Qt.Unchecked item.setCheckState(check) item.setCheckable(True) self.scalarListModel.appendRow(item) self.scalarListView.setModel(self.scalarListModel) def setDefaultScalars(self): setVisible = [] for row in range(self.scalarListModel.rowCount()): item = self.scalarListModel.item(row) if item.checkState() == Qt.Checked: setVisible.append(item.text()) return setVisible def fillPlots(self): plots = [ 'total A,R,T', # requires calc [0] 'Ellipsometry', # requires nothing 'absorption (layerwise)', # requires calc [2] 'collection (layerwise)', # requires calc [2] 'QE', # requires calc [2] 'reflection (interfacewise)', 'generation' # requires calc [3] ] self.plotListModel = QStandardItemModel() plotsToShow = self.defaults['defaultPlots'] for value in plots: item = QStandardItem(value) check = Qt.Checked if value in plotsToShow else Qt.Unchecked item.setCheckState(check) item.setCheckable(True) self.plotListModel.appendRow(item) self.plotListView.setModel(self.plotListModel) def setDefaultPlots(self): setVisible = [] for row in range(self.plotListModel.rowCount()): item = self.plotListModel.item(row) if item.checkState() == Qt.Checked: setVisible.append(item.text()) return setVisible def fillCalculations(self): self.calculations = ['Stack optics (A,R,T)', 'Ellipsometry', 'Field intensity', 'Layerwise optics (absorption, collection, QE)', 'Generation' ] self.calcListModel = QStandardItemModel() calculationsToShow = self.defaults['defaultCalculations'] for value in self.calculations: item = QStandardItem(value) check = Qt.Checked if value in calculationsToShow else Qt.Unchecked item.setCheckState(check) item.setCheckable(True) #item.setEnabled(False) self.calcListModel.appendRow(item) self.calculationsListView.setModel(self.calcListModel) def setDefaultCalculations(self): for row in range(self.calcListModel.rowCount()): item = self.calcListModel.item(row) if item.checkState() == Qt.Checked: highestRow = row setCalcOn = self.calculations[:highestRow+1] return setCalcOn
class LandmarkToolbox(QDockWidget, Ui_DockWidget): landmarkMessage = pyqtSignal(unicode, int) def __init__(self, iface): QDockWidget.__init__(self) self.setupUi(self) self.iface = iface self.canvas = self.iface.mapCanvas() self.geoCrs = QgsCoordinateReferenceSystem(4326) self.btnAddPhoto.setIcon(QIcon(':/icons/camera.svg')) self.txtPhotoComment.setPlaceholderText(self.tr('Comment')) self.cmbLayers.setFilters(QgsMapLayerProxyModel.VectorLayer) self.db = QSqlDatabase.addDatabase('QPSQL') self.landmarkId = None self.photoId = None self.highlight = None self.model = QStandardItemModel() self.lstPhotos.setModel(self.model) self.btnUpdateLandmark.clicked.connect(self.saveLandmark) self.btnDeleteLandmark.clicked.connect(self.deleteLandmark) self.btnAddPhoto.clicked.connect(self.addPhoto) self.btnUpdatePhoto.clicked.connect(self.savePhoto) self.btnDeletePhoto.clicked.connect(self.removePhoto) self.lstPhotos.selectionModel().selectionChanged.connect( self.photoSelected) self.lstPhotos.doubleClicked.connect(self.showPhoto) self._enableOrDisableButtons() self.ToggleToolbox() def ToggleToolbox(self): layer_list = self.canvas.layers() if not layer_list: self.hide() return elif len(layer_list) == 0: self.hide() return self.setVisible(not self.isVisible()) def getLandmarkID(self): #ランドマークがなかった時の処理 return self.landmarkId def openDatabase(self): if self.db.isValid(): settings = QSettings('MatsueGkukan', 'Gkukandb') dbHostName = settings.value('hostname') dbDatabaseName = settings.value('databasename') dbUserName = settings.value('username') dbPassword = settings.value('dbpassword') self.db.setHostName(dbHostName) self.db.setDatabaseName(dbDatabaseName) self.db.setUserName(dbUserName) self.db.setPassword(dbPassword) if not self.db.open(): self.GKukanMusiumMessage.emit( self.tr('Can not open GKukanMusium database'), QgsMessageBar.WARNING) return False self.query = QSqlQuery(self.db) return True else: settings = QSettings('MatsueGkukan', 'Gkukandb') dbHostName = settings.value('hostname') dbDatabaseName = settings.value('databasename') dbUserName = settings.value('username') dbPassword = settings.value('dbpassword') self.db.removeDatabase(dbDatabaseName) del self.db self.db = None self.db = QSqlDatabase.addDatabase('QPSQL') self.db.setHostName(dbHostName) self.db.setDatabaseName(dbDatabaseName) self.db.setUserName(dbUserName) self.db.setPassword(dbPassword) if not self.db.open(): self.GKukanMusiumMessage.emit( self.tr('Can not open GKukanMusium database'), QgsMessageBar.WARNING) return False self.query = QSqlQuery(self.db) return True return False def GetPhotoFolderPath(self): if not self.openDatabase(): return False if self.query.exec_(u'select * from m_folder'): self.query.first() self.folderpath = self.query.value(2) self.thumbpath = os.path.join(self.folderpath, 'thumb') ret = self.folderpath else: ret = '' self.db.close() return ret def landmarkSelected(self, infos): self.info = infos[0] ft = self.info[1] self.landmarkId = ft['id'] self.leLandmarkTitle.setText(ft['title'] if ft['title'] else '') self.spnLandmarkClass.setValue( ft['icon_type'] if ft['icon_type'] != None else 0) self._highlightLandmark() self.populatePhotos() self._enableOrDisableButtons() def populatePhotos(self, index=0): self.model.clear() QApplication.setOverrideCursor(Qt.WaitCursor) # photos is a list of tuples (id, title, imagepath) photos = self._photosOfLandmark() for i in photos: tp = os.path.join(self.thumbpath, str(i[0])) + '.png' img = self.thumbnailPhoto(i[2], tp) icon = QIcon(img) title = i[1] if i[1] else '<unnamed photo> %s' % i[0] item = QStandardItem(title) item.setIcon(icon) item.setData(i[0], Qt.UserRole) item.setToolTip(title) self.model.appendRow(item) lastIdx = self.model.indexFromItem(item) idx = self.model.createIndex(0, 0) if self.model.rowCount() > 0: if index == -1: idx = lastIdx elif index > 0: idx = self.model.createIndex(index, 0) self.lstPhotos.selectionModel().select(idx, QItemSelectionModel.Select) else: self._clearForm() QApplication.restoreOverrideCursor() def thumbnailPhoto(self, imagePath, tp): if os.path.exists(tp): return QPixmap(tp) else: if os.path.exists(os.path.dirname(tp)) == False: os.mkdir(os.path.dirname(tp)) pixmap = QPixmap(imagePath).scaled(800, 600).scaled( 75, 50, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) a = pixmap.save(tp, 'PNG') return pixmap def showPhoto(self, index): if not self.openDatabase(): return item = self.lstPhotos.model().itemFromIndex(index) self.query.prepare( 'SELECT filename ,ST_X(geom),ST_Y(geom),geom FROM t_photo WHERE p_id=?;' ) self.query.addBindValue(item.data(Qt.UserRole)) if self.query.exec_(): self.query.first() path = os.path.join(self.folderpath, self.query.value(0)) if self.query.value( 3) <> '010100000000000000000000000000000000000000': lon = self.query.value(1) lat = self.query.value(2) point = self._transformPoint(QgsPoint(lon, lat)) self.canvas.freeze(True) self.canvas.setCenter(point) self.canvas.freeze(False) self.canvas.refresh() dlg = ViewPhotoDialog(path) dlg.exec_() else: a = self.query.lastError().text() self.db.close() def saveLandmark(self): layer = self.info[0] fid = self.info[1].id() idxTitle = layer.fieldNameIndex('title') idxClassification = layer.fieldNameIndex('icon_type') attrs = {idxTitle: self.leLandmarkTitle.text(),\ idxClassification: self.spnLandmarkClass.value() } layer.dataProvider().changeAttributeValues({fid: attrs}) layer.reload() layer.triggerRepaint() self.landmarkMessage.emit(self.tr('Landmark updated.'), QgsMessageBar.INFO) def deleteLandmark(self): layer = self.info[0] fid = self.info[1].id() layer.dataProvider().deleteFeatures([fid]) layer.reload() layer.triggerRepaint() self._clearAllFields() self.landmarkMessage.emit(self.tr('Landmark deleted.'), QgsMessageBar.INFO) def addPhoto(self): if self.landmarkId is not None: settings = QSettings('MatsueGkukan', 'Gkukandb') lastDir = settings.value('lastPhotoDir', '.') fileName = QFileDialog.getOpenFileName(self, self.tr('Select photo'), lastDir, self._createFilter()) if fileName == '': return settings.setValue('lastPhotoDir', QFileInfo(fileName).absoluteDir().absolutePath()) projectPath = self.GetPhotoFolderPath() + os.sep photoPath = os.path.basename(fileName) photoDate = self._photoDate(fileName).toString('yyyy-MM-dd') if not self.openDatabase(): return self.query.prepare( 'INSERT INTO t_photo("cdate", "filename", "landmark_id",lon,lat,angle,geomtype,geom) VALUES(?, ?, ?,?,?,?,?,?);' ) self.query.addBindValue(photoDate) self.query.addBindValue(photoPath) self.query.addBindValue(self.landmarkId) self.query.addBindValue(0) self.query.addBindValue(0) self.query.addBindValue(0) self.query.addBindValue(0) self.query.addBindValue( '010100000000000000000000000000000000000000') if self.query.exec_(): self._copyPhotoToFolder(fileName, self.landmarkId) self.populatePhotos(-1) else: a = self.query.lastError().text() self.db.close() else: self.landmarkMessage.emit( self.tr('Select landmark before adding a photo.'), QgsMessageBar.WARNING) def savePhoto(self): if not self.openDatabase(): return self.query.prepare( 'UPDATE t_photo SET film_no=?, keywords=?, keyword1=?, keyword2=?, keyword3=?, notes=?, mdate=?, registrant=?, comment=?, reference=?, angle=? WHERE p_id=?;' ) self.query.addBindValue(self.lePhotoTitle.text()) self.query.addBindValue(self.leKeywords.text()) self.query.addBindValue(self.leKeyword1.text()) self.query.addBindValue(self.leKeyword2.text()) self.query.addBindValue(self.leKeyword3.text()) self.query.addBindValue(self.txtPhotoComment.toPlainText()) self.query.addBindValue( self.edPhotoDate.dateTime().toString('yyyy-MM-dd')) self.query.addBindValue(self.leRegistrant.text()) self.query.addBindValue(self.leComment.text()) self.query.addBindValue(self.lerRference.text()) self.query.addBindValue(self.spnPhotoAngle.value()) self.query.addBindValue(self.photoId) if self.query.exec_(): self.landmarkMessage.emit(self.tr('Photo updated.'), QgsMessageBar.INFO) self.populatePhotos(self.lstPhotos.currentIndex().row()) else: a = self.query.lastError().text() self.db.close() def removePhoto(self): if not self.openDatabase(): return self.query.prepare('DELETE FROM t_photo WHERE "p_id"=?;') self.query.addBindValue(self.photoId) if self.query.exec_(): self.db.close() self._removePhotofromFolder() self.populatePhotos() def photoSelected(self, current, previous): if not self.openDatabase(): return idx = current.indexes()[0] item = self.lstPhotos.model().itemFromIndex(idx) self.photoId = item.data(Qt.UserRole) self.query.prepare( 'SELECT film_no, filename, keywords, keyword1, keyword2, keyword3, notes, mdate, registrant, comment, reference, angle FROM t_photo WHERE p_id=?;' ) self.query.addBindValue(self.photoId) if self.query.exec_(): self.query.first() self.filename = self.query.value(1) self.lePhotoTitle.setText( self.query.value(0) if self.query.value(0) else '') self.txtPhotoComment.setPlainText( self.query.value(6) if self.query.value(6) else '') self.leKeywords.setText( self.query.value(2) if self.query.value(2) else '') self.leKeyword1.setText( self.query.value(3) if self.query.value(3) else '') self.leKeyword2.setText( self.query.value(4) if self.query.value(4) else '') self.leKeyword3.setText( self.query.value(5) if self.query.value(5) else '') self.leRegistrant.setText( self.query.value(8) if self.query.value(8) else '') self.leComment.setText( self.query.value(9) if self.query.value(9) else '') self.lerRference.setText( self.query.value(10) if self.query.value(10) else '') self.spnPhotoAngle.setValue( int(self.query.value(11)) if self.query.value(11) else 0) self.edPhotoDate.setDateTime( self.query.value(7) if self.query.value(7) else QDateTime. currentDateTime()) self._enableOrDisableButtons() self.db.close() def _photosOfLandmark(self): projectPath = self.GetPhotoFolderPath() if not self.openDatabase(): return photos = [] self.query.prepare( 'SELECT "p_id", "keywords", "filename" FROM t_photo WHERE "landmark_id"=? ORDER BY "p_id";' ) self.query.addBindValue(self.landmarkId) if self.query.exec_(): while self.query.next(): photos.append((self.query.value(0), self.query.value(1), os.path.join(projectPath, self.query.value(2)))) self.db.close() return photos def _createFilter(self): formats = '' for f in QImageReader.supportedImageFormats(): f = unicode(f) if f == 'svg': continue formats += '*.{} *.{} '.format(f.lower(), f.upper()) return self.tr('Image files (%s);;All files (*.*)' % formats[:-1]) def _clearForm(self): self.lePhotoTitle.clear() self.txtPhotoComment.clear() self.leKeyword1.clear() self.leKeyword2.clear() self.leKeyword3.clear() self.leRegistrant.clear() self.leComment.clear() self.lerRference.clear() self.photoId = None self.landmarkId = None def _enableOrDisableButtons(self): if self.landmarkId is None: self.btnAddPhoto.setEnabled(False) else: self.btnAddPhoto.setEnabled(True) if self.photoId is None: self.btnDeletePhoto.setEnabled(False) self.btnUpdatePhoto.setEnabled(False) else: self.btnDeletePhoto.setEnabled(True) self.btnUpdatePhoto.setEnabled(True) def _highlightLandmark(self): self._clearHighlight() self.highlight = QgsHighlight(self.canvas, self.info[1].geometry(), self.info[0]) settings = QSettings() color = QColor( settings.value('/Map/highlight/color', QGis.DEFAULT_HIGHLIGHT_COLOR.name())) alpha = settings.value('/Map/highlight/colorAlpha', QGis.DEFAULT_HIGHLIGHT_COLOR.alpha(), type=int) buffer = settings.value('/Map/highlight/buffer', QGis.DEFAULT_HIGHLIGHT_BUFFER_MM, type=float) minWidth = settings.value('/Map/highlight/minWidth', QGis.DEFAULT_HIGHLIGHT_MIN_WIDTH_MM, type=float) self.highlight.setColor(color) color.setAlpha(alpha) self.highlight.setFillColor(color) self.highlight.setBuffer(buffer) self.highlight.setMinWidth(minWidth) self.highlight.show() def _photoDate(self, path): with open(path, 'rb') as imgFile: tags = exifread.process_file(imgFile, details=False) if 'EXIF GPS GPSDate' in tags: return QDateTime.fromString(tags['EXIF GPS GPSDate'].values, 'yyyy:MM:dd') else: return QDateTime.currentDateTime() def _clearHighlight(self): if hasattr(self, 'highlight'): del self.highlight self.highlight = None def _clearAllFields(self): self.leLandmarkTitle.clear() self.spnLandmarkClass.clear() self._clearHighlight() self._clearForm() self.model.clear() def _copyPhotoToFolder(self, path, landmark_id): projectPath = self.GetPhotoFolderPath() dst = os.path.join(projectPath, os.path.basename(path)) shutil.copy2(path, dst) def _removePhotofromFolder(self, path, landmark_id): projectPath = self.GetPhotoFolderPath() dst = os.path.join(projectPath, path) os.remove(dst) def _transformPoint(self, pnt): crsDest = self.canvas.mapSettings().destinationCrs() xform = QgsCoordinateTransform(self.geoCrs, crsDest) p2 = xform.transform(pnt) return p2
class ModelAtrributesView(QListView): """ Custom QListView implementation that displays checkable model attributes. """ def __init__(self, parent=None, dataModel=None): QListView.__init__(self, parent) self._dataModel = dataModel self._selectedDisplayMapping = OrderedDict() self._attrModel = QStandardItemModel(self) def dataModel(self): """ Returns the data model instance. """ return self._dataModel def setDataModel(self, dataModel): """ Sets the data model. Should be a callable class rather than the class instance. """ if callable(dataModel): self._dataModel = dataModel else: self._dataModel = dataModel.__class__ def load(self): """ Load the model's attributes into the list view. """ if self._dataModel == None: return try: self._loadAttrs(self._dataModel.displayMapping()) except AttributeError: #Ignore error if model does not contain the displayMapping static method pass def _loadAttrs(self, attrMapping): """ Loads display mapping into the list view. """ self._attrModel.clear() self._attrModel.setColumnCount(2) for attrName, displayName in attrMapping.iteritems(): #Exclude row ID in the list, other unique identifier attributes in the model can be used if attrName != "id": displayNameItem = QStandardItem(displayName) displayNameItem.setCheckable(True) attrNameItem = QStandardItem(attrName) self._attrModel.appendRow([displayNameItem, attrNameItem]) self.setModel(self._attrModel) def selectedMappings(self): """ Return a dictionary of field names and their corresponding display values. """ selectedAttrs = {} for i in range(self._attrModel.rowCount()): displayNameItem = self._attrModel.item(i, 0) if displayNameItem.checkState() == Qt.Checked: attrNameItem = self._attrModel.item(i, 1) selectedAttrs[attrNameItem.text()] = displayNameItem.text() return selectedAttrs
class DialListCheckBox(object): """ Dialog with list check box example : 1,2,4,6,8 """ def __init__(self, values, checked_values=[]): self.dial = QDialog() self.result = "" # Layout Principal m_vbl = QVBoxLayout(self.dial) # List item checkable view = QListView() m_vbl.addWidget(view) self.m_sim = QStandardItemModel() view.setModel(self.m_sim) self._load_item(values, checked_values) # List buttons bt_all = QPushButton(self.tr("All")) bt_all.clicked.connect(lambda: self._check_all()) bt_nothing = QPushButton(self.tr("Nothing")) bt_nothing.clicked.connect(lambda: self._check_nothing()) bt_print = QPushButton(self.tr("Ok")) bt_print.clicked.connect(lambda: self._check_ok()) # Sub layout for buttons m_vbh = QHBoxLayout() m_vbl.addLayout(m_vbh) m_vbh.addWidget(bt_all) m_vbh.addWidget(bt_nothing) m_vbh.addWidget(bt_print) def _load_item(self, values, checked_values): """Load item list""" for v in values: item = QStandardItem(str(v)) if v in checked_values: item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) item.setCheckable(True) self.m_sim.appendRow(item) def _check_all(self): """Check all item""" for index in range(self.m_sim.rowCount( )): ## Iteration sur le model (contient la list des items) item = self.m_sim.item(index) if item.isCheckable() and item.checkState( ) == Qt.Unchecked: # Si Unchecked item.setCheckState(Qt.Checked) def _check_nothing(self): """Uncheck all item""" for index in range(self.m_sim.rowCount( )): ## Iteration sur le model (contient la list des items) item = self.m_sim.item(index) if item.isCheckable() and item.checkState( ) == Qt.Checked: # Si Checked item.setCheckState(Qt.Unchecked) def _check_ok(self): """Get value of checked items and exit""" l_value = [] for index in range(self.m_sim.rowCount( )): ## Iteration sur le model (contient la list des items) item = self.m_sim.item(index) if item.isCheckable() and item.checkState( ) == Qt.Checked: # Si Checked l_value.append(str(item.text())) if l_value: s_value = ";".join(l_value) else: s_value = "" self.result = s_value self.dial.close() def run(self): self.dial.setWindowTitle(self.tr("Select values")) self.dial.exec_() return self.result def tr(self, string, context=''): if context == '' or context == None: context = self.__class__.__name__ return QCoreApplication.translate(context, string)
class LogDialog(QDialogWithDpi): """LogDialog for the Freeseer project. It is the dialog window for the log. There is an instance for every FreeseerApp. It has a LogHandler which calls LogDialog's message() method when a new log message is received. The call to message() causes a call to add_entry() which adds the information to a new row in the table. """ def __init__(self, parent=None): super(LogDialog, self).__init__(parent) self.resize(800, 500) self.app = QApplication.instance() icon = QIcon() icon.addPixmap(QPixmap(_fromUtf8(":/freeseer/logo.png")), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) layout = QVBoxLayout() self.setLayout(layout) self.level = 0 self.handler = LogHandler() self.table_model = QStandardItemModel(0, 5) header_names = ["Date", "Level", "Module", "Message", "LevelNo"] date_column = header_names.index("Date") level_column = header_names.index("Level") module_column = header_names.index("Module") self.level_num_column = header_names.index("LevelNo") self.table_model.setHorizontalHeaderLabels(header_names) self.table_view = QTableView() self.table_view.setModel(self.table_model) self.table_view.horizontalHeader().setStretchLastSection(True) self.table_view.setColumnWidth(date_column, self.set_width_with_dpi(125)) self.table_view.setColumnWidth(level_column, self.set_width_with_dpi(60)) self.table_view.setColumnWidth(module_column, self.set_width_with_dpi(250)) self.table_view.setColumnHidden(self.level_num_column, True) self.table_view.setShowGrid(False) self.table_view.horizontalHeader().setClickable(False) self.table_view.verticalHeader().hide() self.table_view.setStyleSheet("""Qtable_view::item { border-bottom: 1px solid lightgrey; selection-background-color: white; selection-color: black; }""") top_panel = QHBoxLayout() self.log_levels = ["Debug", "Info", "Warning", "Error"] self.level_colors = ["#3E4C85", "#269629", "#B0AB21", "#B32020"] self.levels_label = QLabel("Filter Level: ") self.levels_label.setStyleSheet("QLabel { font-weight: bold }") self.current_level_label = QLabel(self.log_levels[0]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format( self.level_colors[0])) self.clear_button = QPushButton("Clear Log") self.levels_slider = QSlider(Qt.Horizontal) self.levels_slider.setStyleSheet(""" QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #E3E3E3); border: 1px solid #707070; width: 10px; margin-top: -4px; margin-bottom: -4px; border-radius: 4px; } QSlider::handle:horizontal:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #DEDEDE, stop:1 #C9C9C9); border: 1px solid #4F4F4F; border-radius: 4px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BFBFBF, stop: 1 #9E9E9E); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #9E9E9E, stop: 1 #858585); border: 1px solid #777; height: 10px; border-radius: 4px; } QSlider::add-page:horizontal { background: #fff; border: 1px solid #707070; height: 10px; border-radius: 4px; }""") self.levels_slider.setRange(0, len(self.log_levels) - 1) self.levels_slider.setTickPosition(QSlider.TicksBelow) self.levels_slider.setTickInterval(1) top_panel.addSpacerItem(self.qspacer_item_with_dpi(10, 0)) top_panel.addWidget(self.levels_label, 3) top_panel.addWidget(self.current_level_label, 2) top_panel.addWidget(self.levels_slider, 8) top_panel.addSpacerItem(self.qspacer_item_with_dpi(25, 0)) top_panel.addWidget(self.clear_button, 10) layout.addLayout(top_panel) layout.addWidget(self.table_view) self.connect(self.clear_button, SIGNAL('clicked()'), functools.partial(self.table_model.setRowCount, 0)) self.connect(self.levels_slider, SIGNAL('valueChanged(int)'), self.slider_set_level) self.setWindowTitle("Log") self.handler.add_listener(self) def __del__(self): self.handler.remove_listener(self) def retranslate(self): self.setWindowTitle(self.app.translate("LogDialog", "Log")) self.clear_button.setText(self.app.translate("LogDialog", "Clear Log")) self.levels_label.setText("{}: ".format( self.app.translate("LogDialog", "Filter Level"))) def message(self, message): """Passes the log fields to add_entry() It is called by LogHandler when a log message is received""" self.add_entry(message["time"], message["level"], message["full_module_name"], message["message"], str(message["levelno"])) def add_entry(self, date, level, module, message, levelno): """Adds the given fields to a new row in the log table It is called by message() when a log message is received""" items = [ QStandardItem(date), QStandardItem(level), QStandardItem(module), QStandardItem(message), QStandardItem(levelno) ] for item in items: item.setEditable(False) self.table_model.appendRow(items) def slider_set_level(self, level): self.current_level_label.setText(self.log_levels[level]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format( self.level_colors[level])) self.set_level(level + 1) def set_level(self, level): """Sets the current level of the LogDialog. Level is based on the selection made in the levels_combo_box. It hides all messages with a lower level.""" self.level = level * 10 for i in range(self.table_model.rowCount()): if int(str(self.table_model.item( i, self.level_num_column).text())) < self.level: self.table_view.setRowHidden(i, True) else: self.table_view.setRowHidden(i, False)
class CheckedListBox(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) while not isinstance(parent, QDialog): parent = parent.parent() self.setObjectName("CheckedListBox" + str(len(parent.findChildren(CheckedListBox)))) self.setObjectName("checkBoxWidget") self.hLayout = QHBoxLayout(self) self.hLayout.setObjectName("hLayout") sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) # self.frame = Frame() self.listView = QListView(self) self.hLayout.addWidget(self.listView) self.stdModel = QStandardItemModel() self.listView.setModel(self.stdModel) self.hasObject = False self.objList = [] self.checkBoxList = [] self.listView.pressed.connect(self.listView_clicked) def listView_clicked(self, index): self.emit(SIGNAL("ItemCheck"), self.stdModel.itemFromIndex(index)) def mouseMoveEvent(self, mouseEvent): pt = mouseEvent.pos() pass def Clear(self): self.stdModel.clear() self.hasObject = False self.objList = [] def Add(self, caption, isCheckedFlag=False): captionStr = "" if isinstance(caption, str) or isinstance(caption, QString): captionStr = caption else: captionStr = caption.ToString() self.hasObject = True self.objList.append([self.stdModel.rowCount(), caption]) item = QStandardItem(captionStr) item.setCheckable(True) if isCheckedFlag: item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) self.stdModel.setItem(self.stdModel.rowCount(), item) # checkBox = QCheckBox(self) # checkBox.setText(captionStr) # checkBox.setChecked(isCheckedFlag) # checkBox.clicked.connect(self.checkBox_clicked) # self.hLayout.addWidget(checkBox) def GetItemChecked(self, index): if self.stdModel.rowCount() > 0: item = self.stdModel.item(index) if item.checkState() == Qt.Unchecked: return False return True return False def get_CheckedItems(self): if not self.stdModel.rowCount() > 0: return [] resultCheckedItems = [] for i in range(self.stdModel.rowCount()): item = self.stdModel.item(i) if item.checkState() == Qt.Checked: flag = False if self.hasObject: for obj in self.objList: if obj[0] == i: resultCheckedItems.append(obj) flag = True break if not flag: resultCheckedItems.append(item) return resultCheckedItems CheckedItems = property(get_CheckedItems, None, None, None) def get_Items(self): if not self.stdModel.rowCount() > 0: return None resultItems = [] for i in range(self.stdModel.rowCount()): item = self.stdModel.item(i) flag = False if self.hasObject: for obj in self.objList: if obj[0] == i: resultItems.append(obj) flag = True break if not flag: resultItems.append(item.text()) return resultItems Items = property(get_Items, None, None, None) def get_Enabled(self): return self.isEnabled() def set_Enabled(self, bool): self.setEnabled(bool) Enabled = property(get_Enabled, set_Enabled, None, None) def get_Visible(self): return self.isVisible() def set_Visible(self, bool): self.setVisible(bool) Visible = property(get_Visible, set_Visible, None, None)
class DefaultsDlg(QDialog, Ui_Dialog): """ Class documentation goes here. """ def __init__(self, defaults, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super().__init__(parent) self.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.defaults = defaults self.fillScalars() self.fillPlots() self.fillCalculations() def updateDefaults(self): self.defaults['defaultScalars'] = self.setDefaultScalars() self.defaults['defaultPlots'] = self.setDefaultPlots() self.defaults['defaultCalculations'] = self.setDefaultCalculations() def fillScalars(self): scalars = [ 'absorbance (%)', 'reflectance (%)', 'transmittance (%)', 'absorbance (mA/cm²)', 'reflectance (mA/cm²)', 'transmittance (mA/cm²)', 'generation', 'Jmax (mA/cm²)', 'absorption layerwise (%)', 'absorption layerwise (mA/cm²)', 'collection layerwise (%)', 'collection layerwise (mA/cm²)', 'calc. time (s)' ] self.scalarListModel = QStandardItemModel() scalarsToShow = self.defaults['defaultScalars'] for value in scalars: item = QStandardItem(value) check = Qt.Checked if value in scalarsToShow else Qt.Unchecked item.setCheckState(check) item.setCheckable(True) self.scalarListModel.appendRow(item) self.scalarListView.setModel(self.scalarListModel) def setDefaultScalars(self): setVisible = [] for row in range(self.scalarListModel.rowCount()): item = self.scalarListModel.item(row) if item.checkState() == Qt.Checked: setVisible.append(item.text()) return setVisible def fillPlots(self): plots = [ 'total A,R,T', # requires calc [0] 'Ellipsometry', # requires nothing 'absorption (layerwise)', # requires calc [2] 'collection (layerwise)', # requires calc [2] 'QE', # requires calc [2] 'reflection (interfacewise)', 'generation' # requires calc [3] ] self.plotListModel = QStandardItemModel() plotsToShow = self.defaults['defaultPlots'] for value in plots: item = QStandardItem(value) check = Qt.Checked if value in plotsToShow else Qt.Unchecked item.setCheckState(check) item.setCheckable(True) self.plotListModel.appendRow(item) self.plotListView.setModel(self.plotListModel) def setDefaultPlots(self): setVisible = [] for row in range(self.plotListModel.rowCount()): item = self.plotListModel.item(row) if item.checkState() == Qt.Checked: setVisible.append(item.text()) return setVisible def fillCalculations(self): self.calculations = [ 'Stack optics (A,R,T)', 'Ellipsometry', 'Field intensity', 'Layerwise optics (absorption, collection, QE)', 'Generation' ] self.calcListModel = QStandardItemModel() calculationsToShow = self.defaults['defaultCalculations'] for value in self.calculations: item = QStandardItem(value) check = Qt.Checked if value in calculationsToShow else Qt.Unchecked item.setCheckState(check) item.setCheckable(True) #item.setEnabled(False) self.calcListModel.appendRow(item) self.calculationsListView.setModel(self.calcListModel) def setDefaultCalculations(self): for row in range(self.calcListModel.rowCount()): item = self.calcListModel.item(row) if item.checkState() == Qt.Checked: highestRow = row setCalcOn = self.calculations[:highestRow + 1] return setCalcOn
class OWConfusionMatrix(widget.OWWidget): """Confusion matrix widget""" name = "Confusion Matrix" description = "Display a confusion matrix constructed from " \ "the results of classifier evaluations." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [("Evaluation Results", Orange.evaluation.Results, "set_results")] outputs = [("Selected Data", Orange.data.Table)] quantities = ["Number of instances", "Proportion of predicted", "Proportion of actual"] settingsHandler = settings.ClassValuesContextHandler() selected_learner = settings.Setting([0], schema_only=True) selection = settings.ContextSetting(set()) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) UserAdviceMessages = [ widget.Message( "Clicking on cells or in headers outputs the corresponding " "data instances", "click_cell")] def __init__(self): super().__init__() self.data = None self.results = None self.learners = [] self.headers = [] box = gui.vBox(self.controlArea, "Learners") self.learners_box = gui.listBox( box, self, "selected_learner", "learners", callback=self._learner_changed ) box = gui.vBox(self.controlArea, "Show") gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.vBox(self.controlArea, "Select") gui.button(box, self, "Select Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Select Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "Clear Selection", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.vBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Probabilities", callback=self._invalidate) gui.auto_commit(self.controlArea, self, "autocommit", "Send Selected", "Send Automatically") grid = QGridLayout() self.tablemodel = QStandardItemModel(self) view = self.tableview = QTableView( editTriggers=QTableView.NoEditTriggers) view.setModel(self.tablemodel) view.horizontalHeader().hide() view.verticalHeader().hide() view.horizontalHeader().setMinimumSectionSize(60) view.selectionModel().selectionChanged.connect(self._invalidate) view.setShowGrid(False) view.setItemDelegate(BorderedItemDelegate(Qt.white)) view.clicked.connect(self.cell_clicked) grid.addWidget(view, 0, 0) self.mainArea.layout().addLayout(grid) def sizeHint(self): """Initial size""" return QSize(750, 490) def _item(self, i, j): return self.tablemodel.item(i, j) or QStandardItem() def _set_item(self, i, j, item): self.tablemodel.setItem(i, j, item) def _init_table(self, nclasses): item = self._item(0, 2) item.setData("Predicted", Qt.DisplayRole) item.setTextAlignment(Qt.AlignCenter) item.setFlags(Qt.NoItemFlags) self._set_item(0, 2, item) item = self._item(2, 0) item.setData("Actual", Qt.DisplayRole) item.setTextAlignment(Qt.AlignHCenter | Qt.AlignBottom) item.setFlags(Qt.NoItemFlags) self.tableview.setItemDelegateForColumn(0, gui.VerticalItemDelegate()) self._set_item(2, 0, item) self.tableview.setSpan(0, 2, 1, nclasses) self.tableview.setSpan(2, 0, nclasses, 1) font = self.tablemodel.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) for i in (0, 1): for j in (0, 1): item = self._item(i, j) item.setFlags(Qt.NoItemFlags) self._set_item(i, j, item) for p, label in enumerate(self.headers): for i, j in ((1, p + 2), (p + 2, 1)): item = self._item(i, j) item.setData(label, Qt.DisplayRole) item.setFont(bold_font) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) if p < len(self.headers) - 1: item.setData("br"[j == 1], BorderRole) item.setData(QColor(192, 192, 192), BorderColorRole) self._set_item(i, j, item) hor_header = self.tableview.horizontalHeader() if len(' '.join(self.headers)) < 120: hor_header.setResizeMode(QHeaderView.ResizeToContents) else: hor_header.setDefaultSectionSize(60) self.tablemodel.setRowCount(nclasses + 3) self.tablemodel.setColumnCount(nclasses + 3) def set_results(self, results): """Set the input results.""" prev_sel_learner = self.selected_learner.copy() self.clear() self.warning() self.closeContext() data = None if results is not None and results.data is not None: data = results.data if data is not None and not data.domain.has_discrete_class: self.warning("Confusion Matrix cannot show regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is None: self.report_button.setDisabled(True) else: self.report_button.setDisabled(False) nmodels = results.predicted.shape[0] self.headers = class_values + \ [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'learner_names' is set in 'Test Learners' widget. if hasattr(results, "learner_names"): self.learners = results.learner_names else: self.learners = ["Learner #{}".format(i + 1) for i in range(nmodels)] self._init_table(len(class_values)) self.openContext(data.domain.class_var) if not prev_sel_learner or prev_sel_learner[0] >= len(self.learners): self.selected_learner[:] = [0] else: self.selected_learner[:] = prev_sel_learner self._update() self._set_selection() self.unconditional_commit() def clear(self): """Reset the widget, clear controls""" self.results = None self.data = None self.tablemodel.clear() self.headers = [] # Clear learners last. This action will invoke `_learner_changed` self.learners = [] def select_correct(self): """Select the diagonal elements of the matrix""" selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_wrong(self): """Select the off-diagonal elements of the matrix""" selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_none(self): """Reset selection""" self.tableview.selectionModel().clear() def cell_clicked(self, model_index): """Handle cell click event""" i, j = model_index.row(), model_index.column() if not i or not j: return n = self.tablemodel.rowCount() index = self.tablemodel.index selection = None if i == j == 1 or i == j == n - 1: selection = QItemSelection(index(2, 2), index(n - 1, n - 1)) elif i in (1, n - 1): selection = QItemSelection(index(2, j), index(n - 1, j)) elif j in (1, n - 1): selection = QItemSelection(index(i, 2), index(i, n - 1)) if selection is not None: self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def commit(self): """Output data instances corresponding to selected cells""" if self.results is not None and self.data is not None \ and self.selected_learner: indices = self.tableview.selectedIndexes() indices = {(ind.row() - 2, ind.column() - 2) for ind in indices} actual = self.results.actual learner_name = self.learners[self.selected_learner[0]] predicted = self.results.predicted[self.selected_learner[0]] selected = [i for i, t in enumerate(zip(actual, predicted)) if t in indices] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values ) metas = metas + (var,) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[self.selected_learner[0], selected] extra.append(numpy.array(probs, dtype=object)) pvars = [Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] row_ids = self.data.ids[row_indices] M = numpy.hstack((M,) + tuple(extra)) domain = Orange.data.Domain( self.data.domain.attributes, self.data.domain.class_vars, metas ) data = Orange.data.Table.from_numpy(domain, X, Y, M) data.ids = row_ids data.name = learner_name else: data = None self.send("Selected Data", data) def _invalidate(self): indices = self.tableview.selectedIndexes() self.selection = {(ind.row() - 2, ind.column() - 2) for ind in indices} self.commit() def _set_selection(self): selection = QItemSelection() index = self.tableview.model().index for row, col in self.selection: sel = index(row + 2, col + 2) selection.select(sel, sel) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def _learner_changed(self): self._update() self._set_selection() self.commit() def _update(self): def _isinvalid(x): return isnan(x) or isinf(x) # Update the displayed confusion matrix if self.results is not None and self.selected_learner: cmatrix = confusion_matrix(self.results, self.selected_learner[0]) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) n = len(cmatrix) diag = numpy.diag_indices(n) colors = cmatrix.astype(numpy.double) colors[diag] = 0 if self.selected_quantity == 0: normalized = cmatrix.astype(numpy.int) formatstr = "{}" div = numpy.array([colors.max()]) else: if self.selected_quantity == 1: normalized = 100 * cmatrix / colsum div = colors.max(axis=0) else: normalized = 100 * cmatrix / rowsum[:, numpy.newaxis] div = colors.max(axis=1)[:, numpy.newaxis] formatstr = "{:2.1f} %" div[div == 0] = 1 colors /= div colors[diag] = normalized[diag] / normalized[diag].max() for i in range(n): for j in range(n): val = normalized[i, j] col_val = colors[i, j] item = self._item(i + 2, j + 2) item.setData( "NA" if _isinvalid(val) else formatstr.format(val), Qt.DisplayRole) bkcolor = QColor.fromHsl( [0, 240][i == j], 160, 255 if _isinvalid(col_val) else int(255 - 30 * col_val)) item.setData(QBrush(bkcolor), Qt.BackgroundRole) item.setData("trbl", BorderRole) item.setToolTip("actual: {}\npredicted: {}".format( self.headers[i], self.headers[j])) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self._set_item(i + 2, j + 2, item) bold_font = self.tablemodel.invisibleRootItem().font() bold_font.setBold(True) def _sum_item(value, border=""): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) item.setData(border, BorderRole) item.setData(QColor(192, 192, 192), BorderColorRole) return item for i in range(n): self._set_item(n + 2, i + 2, _sum_item(int(colsum[i]), "t")) self._set_item(i + 2, n + 2, _sum_item(int(rowsum[i]), "l")) self._set_item(n + 2, n + 2, _sum_item(int(rowsum.sum()))) def send_report(self): """Send report""" if self.results is not None and self.selected_learner: self.report_table( "Confusion matrix for {} (showing {})". format(self.learners[self.selected_learner[0]], self.quantities[self.selected_quantity].lower()), self.tableview)
class DirDocumentTypeSelector(QDialog): """ Dialog for selecting supporting documents from a given directory. Default filter searches for PDF files only. """ def __init__(self, dir, doc_types, parent=None, filters=None): super(DirDocumentTypeSelector, self).__init__(parent) self.setWindowTitle( self.tr('Documents in Folder') ) self._filters = filters # Use PDF as default filter if not self._filters: self._filters = ['*.pdf'] self._init_ui() self._dir = QDir(dir) self._dir.setNameFilters(self._filters) self._doc_types = doc_types self._attr_model = QStandardItemModel(self) self._sel_doc_types = OrderedDict() # Notification bar self._notif_bar = NotificationBar(self.vl_notif) self.resize(320, 350) # Load documents self.load_document_types() @property def selected_document_types(self): """ :return: Returns a dictionary of the document types and the corresponding file paths as selected by the user. :rtype: dict """ return self._sel_doc_types def _init_ui(self): # Draw UI widgets layout = QVBoxLayout() # Add layout for notification bar self.vl_notif = QVBoxLayout() layout.addLayout(self.vl_notif) self.lbl_info = QLabel() self.lbl_info.setObjectName('lbl_info') self.lbl_info.setText(self.tr( 'The selected document types have been found in the directory, ' 'check/uncheck to specify which ones to upload.' )) self.lbl_info.setWordWrap(True) layout.addWidget(self.lbl_info) self.lst_docs = QListView() layout.addWidget(self.lst_docs) self.lbl_warning = QLabel() self.lbl_warning.setTextFormat(Qt.RichText) self.lbl_warning.setText(self.tr( '<html><head/><body><p><span style=" font-style:italic;">' '* Previously uploaded documents will be replaced.</span></p>' '</body></html>' )) self.lbl_warning.setWordWrap(True) layout.addWidget(self.lbl_warning) self.btn_box = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) layout.addWidget(self.btn_box) self.setLayout(layout) # Connect signals self.btn_box.accepted.connect( self.set_selected_document_types ) self.btn_box.rejected.connect( self.reject ) def set_selected_document_types(self): """ Sets the collections of accepted document types and their corresponding file paths and accepts the dialog. """ self._sel_doc_types = OrderedDict() for i in range(self._attr_model.rowCount()): doc_type_item = self._attr_model.item(i, 0) if doc_type_item.checkState() == Qt.Checked: path_item = self._attr_model.item(i, 1) self._sel_doc_types[doc_type_item.text()] = path_item.text() if len(self._sel_doc_types) == 0: self._notif_bar.clear() msg = self.tr('No matching documents found or selected.') self._notif_bar.insertWarningNotification(msg) return self.accept() def load_document_types(self): """ Load all document types to the list view and enable/check the items for those types that have been found. """ self._attr_model.clear() self._attr_model.setColumnCount(2) file_infos = self._dir.entryInfoList( QDir.Readable | QDir.Files, QDir.Name ) # Index file info based on name idx_file_infos = {fi.completeBaseName().lower(): fi for fi in file_infos} for d in self._doc_types: doc_type_item = QStandardItem(d) doc_type_item.setCheckable(True) path_item = QStandardItem() item_enabled = False check_state = Qt.Unchecked dl = d.lower() if dl in idx_file_infos: item_enabled = True check_state = Qt.Checked path = idx_file_infos[dl].filePath() path_item.setText(path) doc_type_item.setToolTip(path) doc_type_item.setEnabled(item_enabled) doc_type_item.setCheckState(check_state) self._attr_model.appendRow([doc_type_item, path_item]) self.lst_docs.setModel(self._attr_model)
class ConnectionsDialog(QtGui.QDialog, Ui_DlgConnections): on_connect = pyqtSignal(str, str) on_add = pyqtSignal(str, list) on_connection_change = pyqtSignal() on_zoom_change = pyqtSignal() _connections_array = "connections" _table_headers = OrderedDict([("ID", "id"), ("Min. Zoom", "minzoom"), ("Max. Zoom", "maxzoom"), ("Description", "description")]) _OMT = "OpenMapTiles.com" _predefined_connections = { _OMT: "https://free.tilehosting.com/data/v3.json?key={token}" } _tokens = {_OMT: "6irhAXGgsi8TrIDL0211"} def __init__(self, default_browse_directory): QtGui.QDialog.__init__(self) self.setupUi(self) self.options = OptionsGroup(self.grpOptions, self._on_zoom_change) self.settings = QSettings("VtrSettings") self.connections = {} self.selected_connection = None self.selected_layer_id = None self.cbxConnections.currentIndexChanged['QString'].connect( self._handle_connection_change) self.btnCreateConnection.clicked.connect(self._create_connection) self.btnConnect.clicked.connect(self._handle_connect) self.btnEdit.clicked.connect(self._edit_connection) self.btnDelete.clicked.connect(self._delete_connection) self.btnAdd.clicked.connect(self._load_tiles_for_connection) self.btnSave.clicked.connect(self._export_connections) self.btnLoad.clicked.connect(self._import_connections) self.btnHelp.clicked.connect(lambda: webbrowser.open(_HELP_URL)) self.btnBrowse.clicked.connect(self._select_file_path) self.btnBrowseTrexCache.clicked.connect(self._select_trex_cache_folder) self.open_path = None self.browse_path = default_browse_directory self.model = QStandardItemModel() self.model.setHorizontalHeaderLabels(self._table_headers.keys()) self.tblLayers.setModel(self.model) self._load_connections() self._add_loaded_connections() self.edit_connection_dialog = EditConnectionDialog() _update_size(self) def _select_file_path(self): open_file_name = QFileDialog.getOpenFileName( None, "Select Mapbox Tiles", self.browse_path, "Mapbox Tiles (*.mbtiles)") if open_file_name and os.path.isfile(open_file_name): self.txtPath.setText(open_file_name) self._handle_path_or_folder_selection(open_file_name) def _select_trex_cache_folder(self): open_file_name = QFileDialog.getExistingDirectory( None, "Select t-rex Cache directory", self.browse_path) if open_file_name and os.path.isdir(open_file_name): self.txtTrexCachePath.setText(open_file_name) self._handle_path_or_folder_selection(open_file_name) def _handle_path_or_folder_selection(self, path): self.browse_path = path self.open_path = path name = os.path.basename(path) self.on_connect.emit(name, path) def _on_zoom_change(self): self.on_zoom_change.emit() def set_nr_of_tiles(self, nr_tiles): self.options.set_nr_of_tiles(nr_tiles) def _load_tiles_for_connection(self): indexes = self.tblLayers.selectionModel().selectedRows() selected_layers = map(lambda i: self.model.item(i.row()).text(), indexes) name, url = self._get_current_connection() self.on_add.emit(url, selected_layers) def _export_connections(self): file_name = QFileDialog.getSaveFileName( None, "Export Vector Tile Reader Connections", "", "csv (*.csv)") if file_name: with open(file_name, 'w') as csvfile: fieldnames = ['name', 'url'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for name in self.connections: writer.writerow({ 'name': name, 'url': self.connections[name] }) def _import_connections(self): file_name = QFileDialog.getOpenFileName( None, "Export Vector Tile Reader Connections", "", "csv (*.csv)") if file_name: with open(file_name, 'r') as csvfile: reader = csv.DictReader(csvfile) for row in reader: self._set_connection_url(row['name'], row['url']) self._add_loaded_connections() def _load_connections(self): settings = self.settings connections = settings.beginReadArray(self._connections_array) for i in range(connections): settings.setArrayIndex(i) name = settings.value("name") url = settings.value("url") self._set_connection_url(name, url) settings.endArray() def _add_loaded_connections(self): for index, name in enumerate(self._predefined_connections.keys()): url = self._predefined_connections[name] self._set_connection_url(name, url) for name in sorted(self.connections): is_already_added = self.cbxConnections.findText(name) != -1 if not is_already_added: self.cbxConnections.addItem(name) if len(self.connections) > 0: self.cbxConnections.setCurrentIndex(0) def _delete_connection(self): index = self.cbxConnections.currentIndex() connection = self.cbxConnections.currentText() msg = "Are you sure you want to remove the connection '{}' and all associated settings?".format( connection) reply = QMessageBox.question(self.activateWindow(), 'Confirm Delete', msg, QMessageBox.Yes, QMessageBox.No) if reply == QtGui.QMessageBox.Yes: self.cbxConnections.removeItem(index) self.connections.pop(connection) self._save_connections() def _save_connections(self): settings = self.settings settings.beginWriteArray(self._connections_array) for index, key in enumerate(self.connections): settings.setArrayIndex(index) settings.setValue("name", key) settings.setValue("url", self.connections[key]) settings.endArray() def _set_connection_url(self, name, url): self.connections[name] = url def _handle_connect(self): conn = self._get_current_connection() name = conn[0] url = conn[1] self.on_connect.emit(name, url) self.txtPath.setText("") def _get_current_connection(self): if self.tabServer.isEnabled(): name = self.cbxConnections.currentText() url = self.connections[name] elif self.tabFile.isEnabled(): url = self.txtPath.text() name = os.path.basename(url) else: url = self.txtTrexCachePath.text() name = os.path.basename(url) if name in self._predefined_connections: url = url.replace("{token}", self._tokens[name]) return name, url def show(self): self.exec_() def keep_dialog_open(self): return self.chkKeepOpen.isChecked() def set_layers(self, layers): self.model.removeRows(0, self.model.rowCount()) for row_index, layer in enumerate(layers): for header_index, header in enumerate(self._table_headers.keys()): header_value = self._table_headers[header] if header_value in layer: value = str(layer[header_value]) else: value = "-" self.model.setItem(row_index, header_index, QStandardItem(value)) add_enabled = layers is not None and len(layers) > 0 self.btnAdd.setEnabled(add_enabled) def _edit_connection(self): conn = self._get_current_connection() self._create_or_update_connection(name=conn[0], url=conn[1]) def _create_connection(self): self._create_or_update_connection("", "") def _create_or_update_connection(self, name=None, url=None): self.edit_connection_dialog.set_name_and_path(name, url) result = self.edit_connection_dialog.exec_() if result == QtGui.QDialog.Accepted: newname, newurl = self.edit_connection_dialog.get_connection() self._set_connection_url(newname, newurl) if newname != name: self.cbxConnections.addItem(newname) self.cbxConnections.setCurrentIndex(len(self.connections) - 1) self._save_connections() def _handle_connection_change(self, name): self.set_layers([]) enable_connect = False enable_edit = False if name in self.connections: enable_connect = True enable_edit = name not in self._predefined_connections self.btnConnect.setEnabled(enable_connect) self.btnEdit.setEnabled(enable_edit) self.btnDelete.setEnabled(enable_edit) self.on_connection_change.emit()
class TreeLegend(QObject): toggledLegend = pyqtSignal(list) descriptionLegend = pyqtSignal(str) def __init__(self, treeView): def init(): self.setHeader() self.tree.setModel(self.model) self.headerView.setMovable(False) self.headerView.setClickable(True) self.tree.setSelectionMode(0) # no selection super(TreeLegend, self).__init__() self.tree = treeView # self.hasConnect = self.layer = self.legendItems = None self.visibleItems = [] self.model = QStandardItemModel(0, 1) self.headerView = self.tree.header() # init() self._connect() def __del__(self): if self.hasConnect: self._connect(False) self.model.clear() self.layer.legendChanged.disconnect(self.updateLegendItems) def _connect(self, isConnect=True): ss = [{ 'signal': self.tree.clicked, 'slot': self.toggleItem }, { 'signal': self.headerView.sectionClicked, 'slot': self.toggleHeader }, { 'signal': self.headerView.sectionDoubleClicked, 'slot': self.emitDescription }] if isConnect: self.hasConnect = True for item in ss: item['signal'].connect(item['slot']) else: self.hasConnect = False for item in ss: item['signal'].disconnect(item['slot']) def setHeader(self, data=None): if data is None: self.model.clear() nameHeader = 'Select Raster Layer(Palette)' font = QFont() font.setStrikeOut(False) headerModel = QStandardItem(nameHeader) headerModel.setData(font, Qt.FontRole) tip = "Raster with Palette(Single Band)" headerModel.setData(tip, Qt.ToolTipRole) self.model.setHorizontalHeaderItem(0, headerModel) else: headerModel = self.model.horizontalHeaderItem(0) label = "%s" % data['name'] formatMgs = "Layer: %s\nSource: %s\nNumber Class: %d\nWidth: %d\nHeight: %d\nRes.X: %f\nRes.Y: %f\n\n* Double click copy to Clipboard" dataMsg = (data['name'], data['source'], data['num_class'], data['width'], data['height'], data['resX'], data['resY']) tip = formatMgs % dataMsg headerModel.setData(data, Qt.UserRole) headerModel.setData(label, Qt.DisplayRole) headerModel.setData(tip, Qt.ToolTipRole) def setLayer(self, layer): self.legendItems = layer.legendSymbologyItems() total = len(self.legendItems) self.visibleItems = [True for x in range(total)] data = { 'name': layer.name(), 'source': layer.source(), 'num_class': total, 'width': layer.width(), 'height': layer.height(), 'resX': layer.rasterUnitsPerPixelX(), 'resY': layer.rasterUnitsPerPixelY() } self.setHeader(data) # if not self.layer is None: self.layer.legendChanged.disconnect(self.updateLegendItems) layer.legendChanged.connect(self.updateLegendItems) self.layer = layer def setLegend(self, values): def setHeader(): headerModel = self.model.horizontalHeaderItem(0) data = headerModel.data(Qt.UserRole) data['num_class'] = len(values) self.setHeader(data) def createItem(item): (pixel, total) = item (legend, color) = self.legendItems[pixel] name = "[%d] %s" % (pixel, legend) tip = "Value pixel: %d\nTotal pixels: %d\nClass name: %s" % ( pixel, total, legend) pix = QPixmap(16, 16) pix.fill(color) font.setStrikeOut(not self.visibleItems[pixel]) # itemModel = QStandardItem(QIcon(pix), name) itemModel.setEditable(False) itemModel.setData(font, Qt.FontRole) itemModel.setData(tip, Qt.ToolTipRole) itemModel.setData(item, Qt.UserRole) # return itemModel setHeader() self.model.removeRows(0, self.model.rowCount()) # font = QFont() for item in values: self.model.appendRow(createItem(item)) def setEnabled(self, isEnable=True): self._connect(isEnable) self.tree.setEnabled(isEnable) def getLayerName(self): headerModel = self.model.horizontalHeaderItem(0) return headerModel.data(Qt.UserRole)['name'] @pyqtSlot() def updateLegendItems(self): self.legendItems = self.layer.legendSymbologyItems() # Refresh legend rows = self.model.rowCount() row = 0 while row < rows: index = self.model.index(row, 0) (pixel, total) = self.model.data(index, Qt.UserRole) (legend, color) = self.legendItems[pixel] pix = QPixmap(16, 16) pix.fill(color) self.model.setData(index, QIcon(pix), Qt.DecorationRole) row += 1 @pyqtSlot('QModelIndex') def toggleItem(self, index): font = index.data(Qt.FontRole) strike = not font.strikeOut() font.setStrikeOut(strike) self.model.setData(index, font, Qt.FontRole) # (pixel, total) = index.data(Qt.UserRole) visible = not strike self.visibleItems[pixel] = visible # self.toggledLegend.emit(self.visibleItems) @pyqtSlot(int) def toggleHeader(self, logical): rowCount = self.model.rowCount() if rowCount == 0: return header = self.model.horizontalHeaderItem(0) font = header.data(Qt.FontRole) strike = not font.strikeOut() font.setStrikeOut(strike) header.setData(font, Qt.FontRole) # items = [] row = 0 while row < self.model.rowCount(): index = self.model.index(row, 0) self.model.setData(index, font, Qt.FontRole) items.append(index.data(Qt.UserRole)) row += 1 visible = not strike for item in items: (pixel, total) = item self.visibleItems[pixel] = visible # self.toggledLegend.emit(self.visibleItems) @pyqtSlot(int) def emitDescription(self): def getDescription(): data = self.model.horizontalHeaderItem(0).data(Qt.UserRole) formatMgs = "Layer: %s\nSource: %s\nNumber Class: %d\nWidth: %d\nHeight: %d\nRes.X: %f\nRes.Y: %f" dataMsg = (data['name'], data['source'], data['num_class'], data['width'], data['height'], data['resX'], data['resY']) descHeader = formatMgs % dataMsg # descItems = ["Value pixel;Total pixels;Class name"] rows = self.model.rowCount() row = 0 while row < rows: index = self.model.index(row, 0) (pixel, total) = self.model.data(index, Qt.UserRole) (legend, color) = self.legendItems[pixel] descItems.append("%d;%d;%s" % (pixel, total, legend)) row += 1 return "%s\n\n%s" % (descHeader, '\n'.join(descItems)) if self.model.rowCount() > 0: self.descriptionLegend.emit(getDescription())
class ObstacleTable(QSortFilterProxyModel): MocMultiplier = 1 SelectionMode = SelectionModeType.Automatic def __init__(self, surfacesList, fileWriter=None): QSortFilterProxyModel.__init__(self) ObstacleTable.SelectionMode = SelectionModeType.Automatic self.manualPolygon = None self.surfacesList = surfacesList self.surfaceType = None self.source = QStandardItemModel() self.setSourceModel(self.source) # tableView.hideColumn(self.IndexObjectId) # tableView.hideColumn(self.IndexLayerId) # tableView.hideColumn(self.IndexX) # tableView.hideColumn(self.IndexY) # tableView.hideColumn(self.IndexLat) # tableView.hideColumn(self.IndexLon) # tableView.hideColumn(self.IndexSurface) self.hideColumnLabels = [ ObstacleTableColumnType.ObjectId, ObstacleTableColumnType.LayerId, ObstacleTableColumnType.X, ObstacleTableColumnType.Y, ObstacleTableColumnType.Lat, ObstacleTableColumnType.Lon, ObstacleTableColumnType.Surface ] self.fixedColumnLabels = [ ObstacleTableColumnType.ObjectId, ObstacleTableColumnType.LayerId, ObstacleTableColumnType.Name, ObstacleTableColumnType.X, ObstacleTableColumnType.Y, ObstacleTableColumnType.Lat, ObstacleTableColumnType.Lon, ObstacleTableColumnType.AltM, ObstacleTableColumnType.AltFt, ObstacleTableColumnType.TreesM, ObstacleTableColumnType.TreesFt ] self.IndexObjectId = 0 self.IndexLayerId = 1 self.IndexName = 2 self.IndexX = 3 self.IndexY = 4 self.IndexLat = 5 self.IndexLon = 6 self.IndexAltM = 7 self.IndexAltFt = 8 self.IndexTreesM = 9 self.IndexTreesFt = 10 self.IndexOcaM = -1 self.IndexOcaFt = -1 self.IndexOchM = -1 self.IndexOchFt = -1 self.IndexObstArea = -1 self.IndexDistInSecM = -1 self.IndexMocAppliedM = -1 self.IndexMocAppliedFt = -1 self.IndexMocMultiplier = -1 self.IndexMocReqM = -1 self.IndexMocReqFt = -1 self.IndexDoM = -1 self.IndexDrM = -1 self.IndexDzM = -1 self.IndexDxM = -1 self.IndexDsocM = -1 self.IndexHeightLossM = -1 self.IndexHeightLossFt = -1 self.IndexAcAltM = -1 self.IndexAcAltFt = -1 self.IndexAltReqM = -1 self.IndexAltReqFt = -1 self.IndexCritical = -1 self.IndexMACG = -1 self.IndexPDG = -1 self.IndexSurfAltM = -1 self.IndexSurfAltFt = -1 self.IndexDifferenceM = -1 self.IndexDifferenceFt = -1 self.IndexIlsX = -1 self.IndexIlsY = -1 self.IndexEqAltM = -1 self.IndexEqAltFt = -1 self.IndexSurfaceName = -1 self.IndexDisregardable = -1 self.IndexCloseIn = -1 self.IndexTag = -1 self.IndexSurface = -1 self.IndexArea = -1 self.IndexHLAppliedM = -1 self.setHeaderLabels() self.setFilterKeyColumn(self.IndexSurface) self.setSortRole(Qt.UserRole + 1) self.layoutChanged.connect(self.setVerticalHeader) self.btnLocate = None self.tblObstacles = None def FilterDisregardableObstacles(self, state): if state: self.setFilterKeyColumn(self.IndexDisregardable) self.setFilterFixedString("Yes") self.setFilterKeyColumn(self.IndexSurface) def setSurfaceType(self, surfaceType): self.surfaceType = surfaceType def setFilterFixedString(self, filterString): QSortFilterProxyModel.setFilterFixedString(self, filterString) self.setVerticalHeader() if self.btnLocate != None and self.tblObstacles != None: selectedIndexes = self.tblObstacles.selectedIndexes() if len(selectedIndexes) == 0: self.btnLocate.setEnabled(False) else: self.btnLocate.setEnabled(True) def setLocateBtn(self, btnLocate): self.btnLocate = btnLocate self.btnLocate.setEnabled(False) self.btnLocate.clicked.connect(self.btnLocateClicked) def btnLocateClicked(self): if self.tblObstacles == None: return selectedIndexes = self.tblObstacles.selectedIndexes() self.locate(selectedIndexes) def tblObstaclesClicked(self, idx): if len(self.tblObstacles.selectedIndexes()) > 0: self.btnLocate.setEnabled(True) def setTableView(self, tblObstacles): self.tblObstacles = tblObstacles self.tblObstacles.setSelectionBehavior(QAbstractItemView.SelectRows) self.tblObstacles.setSortingEnabled(True) self.tblObstacles.clicked.connect(self.tblObstaclesClicked) self.tblObstacles.verticalHeader().sectionClicked.connect( self.tblObstaclesClicked) pass def setHeaderLabels(self): # print self.setHeaderData(1, Qt.Vertical, 1, Qt.DisplayRole) pass def setVerticalHeader(self): for i in range(self.rowCount()): self.setHeaderData(i, Qt.Vertical, i + 1, Qt.DisplayRole) def setHiddenColumns(self, tableView): tableView.hideColumn(self.IndexObjectId) tableView.hideColumn(self.IndexLayerId) tableView.hideColumn(self.IndexX) tableView.hideColumn(self.IndexY) tableView.hideColumn(self.IndexLat) tableView.hideColumn(self.IndexLon) tableView.hideColumn(self.IndexSurface) def getExtentForLocate(self, sourceRow): extent = None surfaceType = None if self.IndexSurface < 0: surfaceType = self.surfaceType else: surfaceType = self.source.item(sourceRow, self.IndexSurface).text() surfaceLayers = QgisHelper.getSurfaceLayers(self.surfaceType) for sfLayer in surfaceLayers: lId = sfLayer.name() if lId.contains(surfaceType): extent = sfLayer.extent() break return extent def clear(self): self.source.clear() self.source.setHorizontalHeaderLabels(self.fixedColumnLabels) # self.setHeaderLabels() def locate(self, selectedRowIndexes): if selectedRowIndexes == None or len(selectedRowIndexes) <= 0: return sourceRow = self.mapToSource(selectedRowIndexes[0]).row() objectId = int(self.source.item(sourceRow, self.IndexObjectId).text()) layerId = self.source.item(sourceRow, self.IndexLayerId).text() QgisHelper.selectFeature(layerId, objectId) layer = QgsMapLayerRegistry.instance().mapLayer(layerId) crs = define._canvas.mapSettings().destinationCrs() if crs.mapUnits() == QGis.Meters: x = float(self.source.item(sourceRow, self.IndexX).text()) y = float(self.source.item(sourceRow, self.IndexY).text()) extent = QgsRectangle(x - 350, y - 350, x + 350, y + 350) else: x, result1 = self.source.item(sourceRow, self.IndexLon).data().toDouble() y, result2 = self.source.item(sourceRow, self.IndexLat).data().toDouble() extent = QgsRectangle(x - 0.005, y - 0.005, x + 0.005, y + 0.005) point = QgsPoint(x, y) # extent = self.getExtentForLocate(sourceRow) if extent is None: return QgisHelper.zoomExtent(point, extent, 2) pass def loadObstacles(self, surfaceLayers): if self.source.rowCount() > 0: self.source.clear() self.source.setHorizontalHeaderLabels(self.fixedColumnLabels) demEvaluateAg = None existingDemFlag = False obstacleLayersDEM = QgisHelper.getSurfaceLayers(SurfaceTypes.DEM) obstacleLayers = QgisHelper.getSurfaceLayers(SurfaceTypes.Obstacles) if obstacleLayersDEM != None and len(obstacleLayersDEM) > 0: if QMessageBox.question( None, "Question", "Do you want to use DEM for evaluating Obstacle?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: self.loadObstaclesDEM(obstacleLayersDEM, surfaceLayers) if obstacleLayers != None and len(obstacleLayers) > 0: # if QMessageBox.question(None, "Question", "Do you want to use DEM for evaluating Obstacle?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: self.loadObstaclesVector(obstacleLayers, surfaceLayers) return True def loadObstaclesDEM(self, obstacleLayersDEM, surfaceLayers): progressMessageBar = define._messagBar.createMessage( "Loading DEM Obstacles...") self.progress = QProgressBar() self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(self.progress) define._messagBar.pushWidget(progressMessageBar, define._messagBar.INFO) maxium = 0 offset = 0.0 self.progress.setValue(0) wCount = 0 hCount = 0 for ly in obstacleLayersDEM: demDataProvider = ly.dataProvider() boundDem = demDataProvider.extent() xMin = boundDem.xMinimum() xMax = boundDem.xMaximum() yMin = boundDem.yMinimum() yMax = boundDem.yMaximum() bound = QgisHelper.getIntersectExtent( ly, QgsGeometry.fromRect(boundDem), surfaceLayers) # boundGeom = QgsGeometry.fromRect(bound) if bound == None: continue block = ly.dataProvider().block(0, ly.extent(), ly.width(), ly.height()) xMinimum = ly.dataProvider().extent().xMinimum() yMaximum = ly.dataProvider().extent().yMaximum() yMinimum = ly.dataProvider().extent().yMinimum() xMaximum = ly.dataProvider().extent().xMaximum() xOffSet = ly.extent().width() / ly.width() yOffSet = ly.extent().height() / ly.height() offset = xOffSet if bound.xMinimum() < xMinimum: wStartNumber = 0 xStartValue = xMinimum else: wStartNumber = int((bound.xMinimum() - xMinimum) / xOffSet) xStartValue = bound.xMinimum() if yMaximum < bound.yMaximum(): hStartNumber = 0 yStartValue = yMaximum else: hStartNumber = int((yMaximum - bound.yMaximum()) / yOffSet) yStartValue = bound.yMaximum() if bound.xMaximum() > xMaximum: xEndValue = xMaximum else: xEndValue = bound.xMaximum() if yMinimum > bound.yMinimum(): yEndValue = yMinimum else: yEndValue = bound.yMinimum() wCount = int(math.fabs(xEndValue - xStartValue) / xOffSet) hCount = int(math.fabs(yEndValue - yStartValue) / yOffSet) pixelCount = hCount maxium += pixelCount cellSizeWnd = cellsizeWnd(offset, wCount * hCount, maxium * 0.04) cellSizeWnd.setWindowTitle("Input Cell Size") result = cellSizeWnd.exec_() cellRate = 1 if result == 1: offset = cellSizeWnd.cellsize maxium = cellSizeWnd.cellCount + 2 cellRate = cellSizeWnd.cellRate # print cellSizeWnd.textedit1.text() if maxium == 0: return False self.progress.setMaximum(maxium) trees = define._treesDEM tolerance = define._toleranceDEM for obstacleLayer in obstacleLayersDEM: obstacleUnits = obstacleLayer.crs().mapUnits() demDataProvider = obstacleLayer.dataProvider() boundDem = demDataProvider.extent() bound = QgisHelper.getIntersectExtent( obstacleLayer, QgsGeometry.fromRect(boundDem), surfaceLayers) if bound == None: continue boundGeom = QgsGeometry.fromRect(bound) if not boundGeom.intersects(QgsGeometry.fromRect(boundDem)): continue block = obstacleLayer.dataProvider().block(1, obstacleLayer.extent(), obstacleLayer.width(), obstacleLayer.height()) xMinimum = obstacleLayer.extent().xMinimum() yMaximum = obstacleLayer.extent().yMaximum() yMinimum = obstacleLayer.extent().yMinimum() xMaximum = obstacleLayer.extent().xMaximum() xOffSet = obstacleLayer.extent().width() / obstacleLayer.width() yOffSet = obstacleLayer.extent().height() / obstacleLayer.height() if bound.xMinimum() < xMinimum: hStartNumber = 0 xStartValue = xMinimum else: hStartNumber = int((bound.xMinimum() - xMinimum) / xOffSet) xStartValue = bound.xMinimum() if yMaximum < bound.yMaximum(): wStartNumber = 0 yStartValue = yMaximum else: wStartNumber = int((yMaximum - bound.yMaximum()) / yOffSet) yStartValue = bound.yMaximum() if bound.xMaximum() > xMaximum: xEndValue = xMaximum else: xEndValue = bound.xMaximum() if yMinimum > bound.yMinimum(): yEndValue = yMinimum else: yEndValue = bound.yMinimum() wCount = int(math.fabs(xEndValue - xStartValue) / offset) hCount = int(math.fabs(yEndValue - yStartValue) / offset) xPixelWidth = 0.0 yPixelWidth = 0.0 featureID = 0 # i = 0 # k = 0 # altitudeList = [] # self.progress.setValue(0) # while i <= hCount - 1: # j = 0 # while j <= wCount - 1: # if block.isNoData(j * int(cellRate) + wStartNumber, i* int(cellRate) + hStartNumber): # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # altitudeList.append(None) # continue # altitude = block.value(j * int(cellRate) + wStartNumber, i * int(cellRate) + hStartNumber) # altitudeList.append(altitude) # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # i += 1 i = 0 k = 0 name = "DEM" semiXoffset = xOffSet / 2 semiYoffset = yOffSet / 2 while i <= hCount - 1: j = 0 while j <= wCount - 1: if block.isNoData(j * cellRate + wStartNumber, i * cellRate + hStartNumber): self.progress.setValue(k) QApplication.processEvents() j += 1 k += 1 continue altitude = block.value(j * cellRate + wStartNumber, i * cellRate + hStartNumber) # # if block.isNoData(j * int(cellRate) + wStartNumber, i* int(cellRate) + hStartNumber): # # j += 1 # # self.progress.setValue(self.progress.value() + 1) # # QApplication.processEvents() # # continue # # altitude = block.value(j* int(cellRate) + wStartNumber, i* int(cellRate)+ hStartNumber) # altitude = altitudeList[k] # if altitude == None: # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # continue point = QgsPoint( xStartValue + (i * cellRate) * xOffSet + semiXoffset, yStartValue - (j * cellRate - 1) * yOffSet - semiYoffset) position = Point3D() positionDegree = Point3D() if define._canvas.mapUnits() == QGis.Meters: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): position = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: position = Point3D(point.x(), point.y(), altitude) else: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): positionDegree = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: positionDegree = Point3D(point.x(), point.y(), altitude) obstacle = Obstacle(name, position, obstacleLayer.id(), featureID, None, trees, ObstacleTable.MocMultiplier, tolerance) obstacle.positionDegree = positionDegree if self.manualPolygon != None: if not self.manualPolygon.contains(obstacle.Position): continue self.checkObstacle(obstacle) self.progress.setValue(k) QApplication.processEvents() j += 1 featureID += 1 k += 1 i += 1 self.progress.setValue(maxium) define._messagBar.hide() self.manualPolygon = None def loadObstaclesVector(self, obstacleLayers, surfaceLayers): progressMessageBar = define._messagBar.createMessage( "Loading Vector Obstacles...") self.progress = QProgressBar() self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(self.progress) define._messagBar.pushWidget(progressMessageBar, define._messagBar.INFO) maxium = 0 self.progress.setValue(0) for ly in obstacleLayers: maxium += ly.featureCount() if maxium == 0: return False self.progress.setMaximum(maxium) for obstacleLayer in obstacleLayers: obstacleUnits = obstacleLayer.crs().mapUnits() features = QgisHelper.getFeaturesInLayerExtent( define._canvas, obstacleLayer, surfaceLayers, SelectionModeType.Automatic) # print len(features) for feature in features: name = feature.attribute("Name").toString() altitude = feature.attribute("Altitude").toFloat()[0] trees = define._trees tolerance = define._tolerance point = feature.geometry().asPoint() position = Point3D() positionDegree = Point3D() if define._canvas.mapUnits() == QGis.Meters: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): position = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: position = Point3D(point.x(), point.y(), altitude) else: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): positionDegree = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: positionDegree = Point3D(point.x(), point.y(), altitude) featureId = feature.id() layerId = obstacleLayer.id() obstacle = Obstacle(name, position, layerId, featureId, None, trees, ObstacleTable.MocMultiplier, tolerance) obstacle.positionDegree = positionDegree # obstacle.positionDegree = positionDegree self.checkObstacle(obstacle) self.progress.setValue(self.progress.value() + 1) QApplication.processEvents() QApplication.processEvents() self.progress.setValue(maxium) define._messagBar.hide() self.manualPolygon = None def addObstacleToModel(self, obstacle, checkResult=None): standardItemList = [] # obstacle.positionDegree = QgisHelper.Meter2Degree(obstacle.Position.x(), obstacle.Position.y()) standardItem = QStandardItem(str(obstacle.featureId)) standardItem.setData(obstacle.featureId) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.layerId)) standardItem.setData(obstacle.layerId) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.name)) standardItem.setData(obstacle.name) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.x())) standardItem.setData(obstacle.Position.x()) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.y())) standardItem.setData(obstacle.Position.y()) standardItemList.append(standardItem) value = QVariant(QgisHelper.strDegree(obstacle.positionDegree.y())) standardItem = QStandardItem(value.toString()) standardItem.setData(obstacle.positionDegree.y()) standardItemList.append(standardItem) strV = QgisHelper.strDegree(obstacle.positionDegree.y()) value = QVariant(QgisHelper.strDegree(obstacle.positionDegree.x())) standardItem = QStandardItem(value.toString()) standardItem.setData(obstacle.positionDegree.x()) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.z())) standardItem.setData(obstacle.Position.z()) standardItemList.append(standardItem) standardItem = QStandardItem( str(Unit.ConvertMeterToFeet(obstacle.Position.z()))) standardItem.setData(Unit.ConvertMeterToFeet(obstacle.Position.z())) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.trees)) standardItem.setData(obstacle.trees) standardItemList.append(standardItem) standardItem = QStandardItem( str(Unit.ConvertMeterToFeet(obstacle.trees))) standardItem.setData(Unit.ConvertMeterToFeet(obstacle.trees)) standardItemList.append(standardItem) # for i in range(len(standardItemList), self.source.columnCount()): # standardItemList.append(QStandardItem("None")) self.source.appendRow(standardItemList) standardItem = QStandardItem(str(obstacle.mocMultiplier)) standardItem.setData(obstacle.mocMultiplier) self.source.setItem(self.source.rowCount() - 1, self.IndexMocMultiplier, standardItem) def checkObstacle(self, obstacle): pass def CompareObstacleRows(self, newRow, row, ignore): pass def method_0(self, obstacle_0): colCount = self.columnCount() objectId = range(colCount) objectId[0] = (obstacle_0.featureId) objectId[1] = (obstacle_0.name) objectId[2] = (obstacle_0.position.x()) objectId[3] = (obstacle_0.position.y()) objectId[4] = (obstacle_0.Position.z()) position = obstacle_0.position objectId[6] = (Unit.ConvertMeterToFeet(position.z())) objectId[7] = (obstacle_0.trees) objectId[8] = (Unit.ConvertMeterToFeet(obstacle_0.Trees)) if (self.IndexMocMultiplier > -1): objectId[self.IndexMocMultiplier] = obstacle_0.MocMultiplier return objectId def method_1(self, object_0): pass
class PosiviewProperties(QgsOptionsDialogBase, Ui_PosiviewPropertiesBase): ''' GUI class classdocs for the Configuration dialog ''' applyChanges = pyqtSignal(dict) def __init__(self, project, parent=None): ''' Setup dialog widgets with the project properties ''' super(PosiviewProperties, self).__init__("PosiViewProperties", parent) self.setupUi(self) self.groupBox_6.hide() self.initOptionsBase(False) self.restoreOptionsBaseUi() self.comboBoxParser.addItems(PARSERS) self.comboBoxProviderType.addItems(DEVICE_TYPES) self.project = project self.projectProperties = project.properties() self.mToolButtonLoad.setDefaultAction(self.actionLoadConfiguration) self.mToolButtonSave.setDefaultAction(self.actionSaveConfiguration) self.mobileModel = QStringListModel() self.mobileListModel = QStringListModel() self.mMobileListView.setModel(self.mobileListModel) self.mobileProviderModel = QStandardItemModel() self.mobileProviderModel.setHorizontalHeaderLabels(('Provider', 'Filter')) self.mMobileProviderTableView.setModel(self.mobileProviderModel) self.providerListModel = QStringListModel() self.mDataProviderListView.setModel(self.providerListModel) self.comboBoxProviders.setModel(self.providerListModel) self.setupModelData(self.projectProperties) self.setupGeneralData(self.projectProperties) def setupModelData(self, properties): self.mobileListModel.setStringList(sorted(properties['Mobiles'].keys())) self.providerListModel.setStringList(sorted(properties['Provider'].keys())) def setupGeneralData(self, properties): self.lineEditCruise.setText(properties['Mission']['cruise']) self.lineEditDive.setText(properties['Mission']['dive']) self.lineEditStation.setText(properties['Mission']['station']) self.lineEditRecorderPath.setText(properties['RecorderPath']) self.checkBoxAutoRecording.setChecked(properties['AutoRecord']) self.spinBoxNotifyDuration.setValue(properties['NotifyDuration']) self.checkBoxUtcClock.setChecked((properties['ShowUtcClock'])) def updateGeneralData(self): self.projectProperties['Mission']['cruise'] = self.lineEditCruise.text() self.projectProperties['Mission']['dive'] = self.lineEditDive.text() self.projectProperties['Mission']['station'] = self.lineEditStation.text() self.projectProperties['RecorderPath'] = self.lineEditRecorderPath.text() self.projectProperties['AutoRecord'] = self.checkBoxAutoRecording.isChecked() self.projectProperties['NotifyDuration'] = self.spinBoxNotifyDuration.value() self.projectProperties['ShowUtcClock'] = self.checkBoxUtcClock.isChecked() def getColor(self, value): try: return QColor.fromRgba(int(value)) except ValueError: return QColor(value) @pyqtSlot(QAbstractButton, name='on_buttonBox_clicked') def onButtonBoxClicked(self, button): role = self.buttonBox.buttonRole(button) if role == QDialogButtonBox.ApplyRole or role == QDialogButtonBox.AcceptRole: self.updateGeneralData() self.applyChanges.emit(self.projectProperties) @pyqtSlot(name='on_actionSaveConfiguration_triggered') def onActionSaveConfigurationTriggered(self): ''' Save the current configuration ''' fn = QFileDialog.getSaveFileName(None, 'Save PosiView configuration', '', 'Configuration (*.ini *.conf)') self.project.store(fn) @pyqtSlot(name='on_actionLoadConfiguration_triggered') def onActionLoadConfigurationTriggered(self): ''' Load configuration from file ''' fn = QFileDialog.getOpenFileName(None, 'Save PosiView configuration', '', 'Configuration (*.ini *.conf)') self.projectProperties = self.project.read(fn) self.setupModelData(self.projectProperties) self.setupGeneralData(self.projectProperties) @pyqtSlot(QModelIndex, name='on_mMobileListView_clicked') def editMobile(self, index): ''' Populate the widgets with the selected mobiles properties ''' if index.isValid(): self.populateMobileWidgets(index) @pyqtSlot(str, name='on_comboBoxMobileType_currentIndexChanged') def mobileTypeChanged(self, mType): if mType == 'SHAPE': # self.lineEditMobileShape.setText(str(mobile['shape'])) self.lineEditMobileShape.setEnabled(True) else: self.lineEditMobileShape.setEnabled(False) @pyqtSlot(QModelIndex, name='on_mMobileListView_activated') def activated(self, index): pass @pyqtSlot(name='on_toolButtonAddMobile_clicked') def addMobile(self): self.mobileListModel.insertRow(self.mobileListModel.rowCount()) index = self.mobileListModel.index(self.mobileListModel.rowCount() - 1) self.lineEditMobileName.setText('NewMobile') self.mobileListModel.setData(index, 'NewMobile', Qt.DisplayRole) self.mMobileListView.setCurrentIndex(index) self.applyMobile() @pyqtSlot(name='on_pushButtonApplyMobile_clicked') def applyMobile(self): index = self.mMobileListView.currentIndex() if index.isValid() and not self.lineEditMobileName.text() == '': mobile = dict() mobile['Name'] = self.lineEditMobileName.text() mobile['type'] = self.comboBoxMobileType.currentText() try: t = eval(self.lineEditMobileShape.text()) if t.__class__ is tuple or t.__class__ is dict: mobile['shape'] = t except SyntaxError: mobile['shape'] = ((0.0, -0.5), (0.3, 0.5), (0.0, 0.2), (-0.5, 0.5)) mobile['length'] = self.doubleSpinBoxMobileLength.value() mobile['width'] = self.doubleSpinBoxMobileWidth.value() mobile['zValue'] = self.spinBoxZValue.value() mobile['color'] = self.mColorButtonMobileColor.color().rgba() mobile['fillColor'] = self.mColorButtonMobileFillColor.color().rgba() mobile['timeout'] = self.spinBoxMobileTimeout.value() * 1000 mobile['nofixNotify'] = self.spinBoxMobileNotification.value() mobile['trackLength'] = self.spinBoxTrackLength.value() mobile['trackColor'] = self.mColorButtonMobileTrackColor.color().rgba() provs = dict() for r in range(self.mobileProviderModel.rowCount()): try: fil = int(self.mobileProviderModel.item(r, 1).data(Qt.DisplayRole)) except: fil = self.mobileProviderModel.item(r, 1).data(Qt.DisplayRole) if not fil: fil = None provs[self.mobileProviderModel.item(r, 0).data(Qt.DisplayRole)] = fil mobile['provider'] = provs currName = self.mobileListModel.data(index, Qt.DisplayRole) if not currName == mobile['Name']: del self.projectProperties['Mobiles'][currName] self.mobileListModel.setData(index, mobile['Name'], Qt.DisplayRole) self.projectProperties['Mobiles'][mobile['Name']] = mobile def populateMobileWidgets(self, index): mobile = self.projectProperties['Mobiles'][self.mobileListModel.data(index, Qt.DisplayRole)] self.lineEditMobileName.setText(mobile.get('Name')) self.comboBoxMobileType.setCurrentIndex(self.comboBoxMobileType.findText(mobile.setdefault('type', 'BOX').upper())) if mobile['type'] == 'SHAPE': self.lineEditMobileShape.setText(str(mobile['shape'])) self.lineEditMobileShape.setEnabled(True) else: self.lineEditMobileShape.setEnabled(False) self.lineEditMobileShape.clear() self.doubleSpinBoxMobileLength.setValue(mobile.get('length', 20.0)) self.doubleSpinBoxMobileWidth.setValue(mobile.get('width', 5.0)) self.spinBoxZValue.setValue(mobile.get('zValue', 100)) self.mColorButtonMobileColor.setColor(self.getColor(mobile.get('color', 'black'))) self.mColorButtonMobileFillColor.setColor(self.getColor(mobile.get('fillColor', 'green'))) self.spinBoxMobileTimeout.setValue(mobile.get('timeout', 3000) / 1000) self.spinBoxMobileNotification.setValue(mobile.get('nofixNotify', 0)) self.spinBoxTrackLength.setValue(mobile.get('trackLength', 100)) self.mColorButtonMobileTrackColor.setColor(self.getColor(mobile.get('trackColor', 'green'))) r = 0 self.mobileProviderModel.removeRows(0, self.mobileProviderModel.rowCount()) if 'provider' in mobile: for k, v in mobile['provider'].items(): prov = QStandardItem(k) val = QStandardItem(str(v)) self.mobileProviderModel.setItem(r, 0, prov) self.mobileProviderModel.setItem(r, 1, val) r += 1 @pyqtSlot(name='on_toolButtonRemoveMobile_clicked') def removeMobile(self): idx = self.mMobileListView.currentIndex() if idx.isValid(): self.projectProperties['Mobiles'].pop(self.mobileListModel.data(idx, Qt.DisplayRole)) self.mobileListModel.removeRows(idx.row(), 1) idx = self.mMobileListView.currentIndex() if idx.isValid(): self.populateMobileWidgets(idx) @pyqtSlot(name='on_toolButtonRefreshMobileProvider_clicked') def refreshMobileProvider(self): prov = self.comboBoxProviders.currentText() if prov == '': return fil = None if self.lineEditProviderFilter.text() != '': fil = self.lineEditProviderFilter.text() items = self.mobileProviderModel.findItems(prov, Qt.MatchExactly, 0) if items: for item in items: self.mobileProviderModel.setItem(item.row(), 1, QStandardItem(fil)) else: self.mobileProviderModel.appendRow([QStandardItem(prov), QStandardItem(fil)]) @pyqtSlot(name='on_toolButtonRemoveMobileProvider_clicked') def removeMobileProvider(self): idx = self.mMobileProviderTableView.currentIndex() if idx.isValid(): self.mobileProviderModel.removeRow(idx.row()) @pyqtSlot(name='on_pushButtonApplyDataProvider_clicked') def applyDataProvider(self): index = self.mDataProviderListView.currentIndex() if index.isValid() and not self.lineEditProviderName.text() == '': provider = dict() provider['Name'] = self.lineEditProviderName.text() provider['DataDeviceType'] = self.comboBoxProviderType.currentText() if provider['DataDeviceType'] in NETWORK_TYPES: provider['Host'] = self.lineEditProviderHostName.text() provider['Port'] = self.spinBoxProviderPort.value() provider['Parser'] = self.comboBoxParser.currentText() currName = self.providerListModel.data(index, Qt.DisplayRole) if not currName == provider['Name']: del self.projectProperties['Provider'][currName] self.providerListModel.setData(index, provider['Name'], Qt.DisplayRole) self.projectProperties['Provider'][provider['Name']] = provider @pyqtSlot(QModelIndex, name='on_mDataProviderListView_clicked') def editDataProvider(self, index): ''' ''' if index.isValid(): self.populateDataProviderWidgets(index) def populateDataProviderWidgets(self, index): provider = self.projectProperties['Provider'][self.providerListModel.data(index, Qt.DisplayRole)] self.lineEditProviderName.setText(provider.get('Name')) self.comboBoxProviderType.setCurrentIndex(self.comboBoxProviderType.findText(provider.setdefault('DataDeviceType', 'UDP').upper())) if provider['DataDeviceType'] in NETWORK_TYPES: self.stackedWidgetDataDevice.setCurrentIndex(0) self.lineEditProviderHostName.setText(provider.setdefault('Host', '0.0.0.0')) self.spinBoxProviderPort.setValue(int(provider.setdefault('Port', 2000))) self.comboBoxParser.setCurrentIndex(self.comboBoxParser.findText(provider.setdefault('Parser', 'NONE').upper())) @pyqtSlot(name='on_toolButtonAddDataProvider_clicked') def addDataProvider(self): self.providerListModel.insertRow(self.providerListModel.rowCount()) index = self.providerListModel.index(self.providerListModel.rowCount() - 1) self.lineEditProviderName.setText('NewDataProvider') self.providerListModel.setData(index, 'NewDataProvider', Qt.DisplayRole) self.mDataProviderListView.setCurrentIndex(index) self.applyDataProvider() @pyqtSlot(name='on_toolButtonRemoveDataProvider_clicked') def removeDataProvider(self): idx = self.mDataProviderListView.currentIndex() if idx.isValid(): self.projectProperties['Provider'].pop(self.providerListModel.data(idx, Qt.DisplayRole)) self.providerListModel.removeRows(idx.row(), 1) idx = self.mDataProviderListView.currentIndex() if idx.isValid(): self.populateDataProviderWidgets(idx) @pyqtSlot(name='on_toolButtonSelectLogPath_clicked') def selectRecorderPath(self): path = QFileDialog.getExistingDirectory(self, self.tr('Select Recorder Path'), self.lineEditRecorderPath.text(), QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if path != '': self.lineEditRecorderPath.setText(path) @pyqtSlot(QPoint, name='on_lineEditMobileShape_customContextMenuRequested') def mobileShapeContextMenu(self, pos): menu = QMenu(self.lineEditMobileShape) vesselAction = menu.addAction(self.tr('Vessel')) rovAction = menu.addAction(self.tr('ROV')) auvAction = menu.addAction(self.tr('AUV')) arrowAction = menu.addAction(self.tr('Arrow')) selectedAction = menu.exec_(self.lineEditMobileShape.mapToGlobal(pos)) if selectedAction == vesselAction: self.lineEditMobileShape.setText(u'((0, -0.5), (0.5, -0.3), (0.5, 0.5), (-0.5, 0.5), (-0.5, -0.3))') elif selectedAction == rovAction: self.lineEditMobileShape.setText(u'((0.3, -0.5), (0.5, -0.3), (0.5, 0.5), (-0.5, 0.5), (-0.5, -0.3), (-0.3, -0.5))') elif selectedAction == auvAction: self.lineEditMobileShape.setText(u'((0, -0.5), (0.5, -0.3), (0.5, 0.5), (-0.5, 0.5), (-0.5, -0.3))') elif selectedAction == arrowAction: self.lineEditMobileShape.setText(u'((0, -0.5), (0.5, 0.5), (0, 0), (-0.5, 0.5))') @pyqtSlot(name='on_buttonBox_helpRequested') def showHelp(self): """Display application help to the user.""" help_file = os.path.join(os.path.split(os.path.dirname(__file__))[0], 'help', 'index.html') QDesktopServices.openUrl(QUrl.fromLocalFile(help_file))
class ListWidget(EditorWidget): widgettype = 'List' def __init__(self, *args, **kwargs): super(ListWidget, self).__init__(*args) self.listmodel = QStandardItemModel() self._bindvalue = None def createWidget(self, parent): return QComboBox(parent) def _buildfromlist(self, widget, listconfig): items = listconfig['items'] for item in items: parts = item.split(';') data = parts[0] try: desc = parts[1] except IndexError: desc = data try: path = parts[2] path = path.strip() icon = QIcon(path) except: icon = QIcon() item = QStandardItem(desc) item.setData(data, Qt.UserRole) item.setIcon(icon) self.listmodel.appendRow(item) def _buildfromlayer(self, widget, layerconfig): layername = layerconfig['layer'] keyfield = layerconfig['key'] valuefield = layerconfig['value'] filterexp = layerconfig.get('filter', None) try: layer = QgsMapLayerRegistry.instance().mapLayersByName( layername)[0] except IndexError: roam.utils.warning( "Can't find layer {} in project".format(layername)) return keyfieldindex = layer.fieldNameIndex(keyfield) valuefieldindex = layer.fieldNameIndex(valuefield) if keyfieldindex == -1 or valuefieldindex == -1: roam.utils.warning("Can't find key or value column") return if self.allownulls: item = QStandardItem('(no selection)') item.setData(None, Qt.UserRole) self.listmodel.appendRow(item) attributes = {keyfieldindex, valuefieldindex} iconfieldindex = layer.fieldNameIndex('icon') if iconfieldindex > -1: attributes.add(iconfieldindex) if not filterexp and valuefieldindex == keyfieldindex and iconfieldindex == -1: values = layer.uniqueValues(keyfieldindex) for value in values: value = nullconvert(value) item = QStandardItem(value) item.setData(value, Qt.UserRole) self.listmodel.appendRow(item) return flags = QgsFeatureRequest.NoGeometry expression = None if filterexp: expression = QgsExpression(filterexp) expression.prepare(layer.pendingFields()) if expression.hasParserError(): roam.utils.warning("Expression has parser error: {}".format( expression.parserErrorString())) return if expression.needsGeometry(): flags = QgsFeatureRequest.NoFlags for field in expression.referencedColumns(): index = layer.fieldNameIndex(field) attributes.add(index) request = QgsFeatureRequest().setFlags(flags).setSubsetOfAttributes( list(attributes)) for feature in layer.getFeatures(request): if expression and not expression.evaluate(feature): continue keyvalue = nullconvert(feature[keyfieldindex]) valuvalue = nullconvert(feature[valuefield]) try: path = feature[iconfieldindex] icon = QIcon(path) except KeyError: icon = QIcon() item = QStandardItem(unicode(keyvalue)) item.setData(unicode(valuvalue), Qt.UserRole) item.setIcon(icon) self.listmodel.appendRow(item) def initWidget(self, widget, config): if widget.isEditable(): widget.editTextChanged.connect(self.emitvaluechanged) widget.currentIndexChanged.connect(self.emitvaluechanged) widget.setModel(self.listmodel) widget.showPopup = self.showpopup widget.setIconSize(QSize(24, 24)) widget.setStyleSheet( "QComboBox::drop-down {border-width: 0px;} QComboBox::down-arrow {image: url(noimg); border-width: 0px;}" ) widget.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) def showpopup(self): if self.listmodel.rowCount() == 0: return self.largewidgetrequest.emit( BigListWidget, self.widget.currentIndex(), self._biglistitem, dict(model=self.listmodel, label=self.labeltext)) def updatefromconfig(self): super(ListWidget, self).updatefromconfig() self.listmodel.clear() if 'list' in self.config: listconfig = self.config['list'] self._buildfromlist(self.widget, listconfig) elif 'layer' in self.config: layerconfig = self.config['layer'] self._buildfromlayer(self.widget, layerconfig) super(ListWidget, self).endupdatefromconfig() @property def allownulls(self): return self.config.get('allownull', False) def validate(self, *args): if (not self.widget.currentText() == '' and not self.widget.currentText() == "(no selection)"): return True else: return False def _biglistitem(self, index): self.widget.setCurrentIndex(index.row()) def setvalue(self, value): self._bindvalue = value index = self.widget.findData(value) self.widget.setCurrentIndex(index) if index == -1 and self.widget.isEditable(): if value is None and not self.config['allownull']: return self.widget.addItem(str(value)) index = self.widget.count() - 1 self.widget.setCurrentIndex(index) def value(self): index = self.widget.currentIndex() value = self.widget.itemData(index) text = self.widget.currentText() if value is None and self.widget.isEditable( ) and not text == '(no selection)': return self.widget.currentText() return value
class Dialog(QDialog, Ui_nbEditor_dialog): def __init__(self, iface, ml, mc): """Constructor for the dialog. Args: iface: QgsInterface instance. """ QDialog.__init__(self, iface.mainWindow()) self.setupUi(self) self.ml = ml self.mCanvas = mc self.mRubberBand = QgsRubberBand(self.mCanvas, True) self.mRubberBand.reset(QGis.Polygon) self.mRubberBand.setColor(Qt.red) self.mRubberBand.setWidth(2) self.ids = [] self.ini(0) self.pushCancel.clicked.connect(self.close) self.pushOK.clicked.connect(self.convert) self.comboBox.addItems(['','Intersections','Touches','Within distance']) self.comboBox.currentIndexChanged.connect(self.nbMethod) self.ml.selectionChanged.connect(self.map2tab) def ini(self, n): self.model = QStandardItemModel(n, 1) self.tableView.setModel(self.model) self.model.setHeaderData(0, Qt.Horizontal, 'Neighbouring IDs') self.tableView.setSelectionMode(QAbstractItemView.SingleSelection) self.selectionModel = QItemSelectionModel(self.model) self.tableView.setSelectionModel(self.selectionModel) self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.selectionModel().selectionChanged.connect(self.tab2map) self.progressBar.setValue(0) def settings(self): self.mod = min(self.ids) self.p = 1 if self.mod==1: self.p = 0 def map2tab(self): s = '' idx = self.tableView.selectionModel().selectedIndexes()[0] ts = str(self.model.itemData(idx)[0]) for fid in sorted(self.ml.selectedFeaturesIds()): s += '%s,' % str(int(fid)+self.p) s = s[:-1] if s!=ts: self.model.setData(idx, s) # in order to handle the symmetry if len(s)>len(ts): iLst = s.strip().replace(' ', '').split(',') jLst = ts.strip().replace(' ', '').split(',') else: iLst = ts.strip().replace(' ', '').split(',') jLst = s.strip().replace(' ', '').split(',') cent = str(idx.row()+self.p) dLst = list(set(iLst)-set(jLst)) for d in dLst: row = int(d)-self.p sor = str(self.model.itemData(self.model.index(row, 0))[0]) eLst = sor.strip().replace(' ', '').split(',') res = '' if cent in set(eLst): ii = eLst.index(cent) del eLst[ii] eLst = sorted(map(int, eLst)) for e in eLst: res += '%s,' % e res = res[:-1] else: u = sor + ',%s' % cent eLst = sorted(map(int, u.strip().replace(' ', '').split(','))) for e in eLst: res += '%s,' % e res = res[:-1] self.model.setData(self.model.index(row, 0, QModelIndex()), res) def nbWithinDist(self): dlg = xdist.Dialog() dlg.setModal(True) dlg.setWindowTitle("Between two objects") if dlg.exec_() == QDialog.Accepted: lDist = float(dlg.lineEdit.text()) if lDist==0: return feat = QgsFeature() provider = self.ml.dataProvider() e = provider.featureCount() self.settings() for ne in range(self.mod, e + self.mod): feat = QgsFeature() geom = QgsGeometry() fiter = self.ml.getFeatures(QgsFeatureRequest(ne)) if fiter.nextFeature(feat): geom = QgsGeometry(feat.geometry()) neighbours = self.hdist(feat, lDist) row = feat.id()-self.mod self.model.setData(self.model.index(row, 0, QModelIndex()), neighbours) self.progressBar.setValue(100*ne/e) def hdist(self, feata, lDist): geoma = QgsGeometry(feata.geometry()) feat = QgsFeature() provider = self.ml.dataProvider() feats = provider.getFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, provider.featureCount())) ne = 0 neighbours = "" while feats.nextFeature(feat): ne += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne) geomb = QgsGeometry(feat.geometry()) if feata.id()!=feat.id(): if geoma.distance(geomb)<=lDist: neighbours = neighbours + '%s,' % (feat.id()+self.p) return neighbours[:-1] def tab2map(self): QApplication.setOverrideCursor(Qt.WaitCursor) self.ml.selectionChanged.disconnect(self.map2tab) idx = self.tableView.selectionModel().selectedIndexes()[0] featureId = idx.row() + self.p s = self.model.itemData(idx) lst = s[0].strip().replace(' ', '').split(',') self.ml.removeSelection() for sid in lst: self.ml.select(int(sid)-self.p) provider = self.ml.dataProvider() feat = QgsFeature() layer = QgsVectorLayerCache(self.ml, provider.featureCount()) layer.featureAtId(idx.row()+self.mod, feat) geom = QgsGeometry(feat.geometry()) self.mRubberBand.setToGeometry(geom, self.ml) self.mRubberBand.show() self.ml.selectionChanged.connect(self.map2tab) QApplication.restoreOverrideCursor() def closeEvent(self,event): QApplication.setOverrideCursor(Qt.WaitCursor) self.ml.selectionChanged.disconnect(self.map2tab) self.ml.removeSelection() self.mRubberBand.hide() self.close() QApplication.restoreOverrideCursor() def convert(self): dlg = editor.Dialog() dlg.setModal(True) dlg.setWindowTitle("Neighbour list in BUGS format") num = "" adj = "" sumNumNeigh = 0 for row in range(0, self.model.rowCount()): ts = self.model.itemData(self.model.index(row, 0)) lst = ts[0].strip().replace(' ', '').split(',') num += '%s, ' % len(lst) sumNumNeigh += len(lst) lst.reverse() sor = ', '.join(lst) + ',' adj = adj + str(sor) + '\n' num = num[:-2] adj = adj[:-2] nblist = 'list(\nnum = c(%s),\nadj = c(%s),\nsumNumNeigh=%s)' % (num, adj, sumNumNeigh) dlg.plainTextEdit.appendPlainText(nblist) dlg.exec_() def nbMethod(self): QApplication.setOverrideCursor(Qt.WaitCursor) self.ml.selectionChanged.disconnect(self.map2tab) self.model.removeRows(0, self.model.rowCount(QModelIndex()), QModelIndex()) n = self.ml.dataProvider().featureCount() self.ini(n) self.ids = [] provider = self.ml.dataProvider() feats = provider.getFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, n)) ne = 0 feat = QgsFeature() while feats.nextFeature(feat): ne += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne) self.ids.append(feat.id()) if self.comboBox.currentText()=="Touches": if self.ml.geometryType()==0: return else: self.nbTouches() if self.comboBox.currentText()=="Intersections": if self.ml.geometryType()==0: return else: self.nbIntersects() if self.comboBox.currentText()=="Within distance": self.nbWithinDist() self.ml.selectionChanged.connect(self.map2tab) QApplication.restoreOverrideCursor() def nbTouches(self): feat = QgsFeature() provider = self.ml.dataProvider() e = provider.featureCount() self.settings() for ne in range(self.mod, e + self.mod): feat = QgsFeature() geom = QgsGeometry() fiter = self.ml.getFeatures(QgsFeatureRequest(ne)) if fiter.nextFeature(feat): geom = QgsGeometry(feat.geometry()) neighbours = self.htouch(feat) row = feat.id()-self.mod self.model.setData(self.model.index(row, 0, QModelIndex()), neighbours) self.progressBar.setValue(100*ne/e) def htouch(self, feata): geoma = QgsGeometry(feata.geometry()) feat = QgsFeature() provider = self.ml.dataProvider() feats = provider.getFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, provider.featureCount())) ne = 0 neighbours = "" while feats.nextFeature(feat): ne += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne) geomb = QgsGeometry(feat.geometry()) if feata.id()!=feat.id(): if geoma.touches(geomb)==True: neighbours = neighbours + '%s,' % (feat.id()+self.p) return neighbours[:-1] def nbIntersects(self): feat = QgsFeature() provider = self.ml.dataProvider() e = provider.featureCount() self.settings() for ne in range(self.mod, e + self.mod): feat = QgsFeature() geom = QgsGeometry() fiter = self.ml.getFeatures(QgsFeatureRequest(ne)) if fiter.nextFeature(feat): geom = QgsGeometry(feat.geometry()) neighbours = self.hintersect(feat) row = feat.id()-self.mod self.model.setData(self.model.index(row, 0, QModelIndex()), neighbours) self.progressBar.setValue(100*ne/e) def hintersect(self, feata): geoma = QgsGeometry(feata.geometry()) feat = QgsFeature() provider = self.ml.dataProvider() feats = provider.getFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, provider.featureCount())) ne = 0 neighbours = "" while feats.nextFeature(feat): ne += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne) geomb = QgsGeometry(feat.geometry()) if feata.id()!=feat.id(): if geoma.intersects(geomb)==True: neighbours = neighbours + '%s,' % (feat.id()+self.p) return neighbours[:-1]
class OWConfusionMatrix(widget.OWWidget): name = "Confusion Matrix" description = "Display confusion matrix constructed from results " \ "of evaluation of classifiers." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [("Evaluation Results", Orange.evaluation.Results, "set_results")] outputs = [("Selected Data", Orange.data.Table)] quantities = [ "Number of instances", "Proportion of predicted", "Proportion of actual" ] selected_learner = settings.Setting([]) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) def __init__(self): super().__init__() self.data = None self.results = None self.learners = [] self.headers = [] box = gui.widgetBox(self.controlArea, "Learners") self.learners_box = gui.listBox(box, self, "selected_learner", "learners", callback=self._learner_changed) box = gui.widgetBox(self.controlArea, "Show") gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.widgetBox(self.controlArea, "Select") gui.button(box, self, "Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "None", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Probabilities", callback=self._invalidate) gui.auto_commit(self.controlArea, self, "autocommit", "Send Data", "Auto send is on") grid = QGridLayout() self.tablemodel = QStandardItemModel(self) view = self.tableview = QTableView( editTriggers=QTableView.NoEditTriggers) view.setModel(self.tablemodel) view.horizontalHeader().hide() view.verticalHeader().hide() view.horizontalHeader().setMinimumSectionSize(60) view.selectionModel().selectionChanged.connect(self._invalidate) view.setShowGrid(False) view.clicked.connect(self.cell_clicked) grid.addWidget(view, 0, 0) self.mainArea.layout().addLayout(grid) def sizeHint(self): return QSize(750, 490) def _item(self, i, j): return self.tablemodel.item(i, j) or QStandardItem() def _set_item(self, i, j, item): self.tablemodel.setItem(i, j, item) def set_results(self, results): """Set the input results.""" self.clear() self.warning([0, 1]) data = None if results is not None: if results.data is not None: data = results.data if data is not None and not data.domain.has_discrete_class: data = None results = None self.warning( 0, "Confusion Matrix cannot be used for regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is not None: nmodels, ntests = results.predicted.shape self.headers = class_values + \ [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'learner_names' is set in 'Test Learners' widget. if hasattr(results, "learner_names"): self.learners = results.learner_names else: self.learners = [ "Learner #%i" % (i + 1) for i in range(nmodels) ] item = self._item(0, 2) item.setData("Predicted", Qt.DisplayRole) item.setTextAlignment(Qt.AlignCenter) item.setFlags(Qt.NoItemFlags) self._set_item(0, 2, item) item = self._item(2, 0) item.setData("Actual", Qt.DisplayRole) item.setTextAlignment(Qt.AlignHCenter | Qt.AlignBottom) item.setFlags(Qt.NoItemFlags) self.tableview.setItemDelegateForColumn(0, gui.VerticalItemDelegate()) self._set_item(2, 0, item) self.tableview.setSpan(0, 2, 1, len(class_values)) self.tableview.setSpan(2, 0, len(class_values), 1) for i in (0, 1): for j in (0, 1): item = self._item(i, j) item.setFlags(Qt.NoItemFlags) self._set_item(i, j, item) for p, label in enumerate(self.headers): for i, j in ((1, p + 2), (p + 2, 1)): item = self._item(i, j) item.setData(label, Qt.DisplayRole) item.setData(QBrush(QColor(208, 208, 208)), Qt.BackgroundColorRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) self._set_item(i, j, item) hor_header = self.tableview.horizontalHeader() if len(' '.join(self.headers)) < 120: hor_header.setResizeMode(QHeaderView.ResizeToContents) else: hor_header.setDefaultSectionSize(60) self.tablemodel.setRowCount(len(class_values) + 3) self.tablemodel.setColumnCount(len(class_values) + 3) self.selected_learner = [0] self._update() def clear(self): self.results = None self.data = None self.tablemodel.clear() self.headers = [] # Clear learners last. This action will invoke `_learner_changed` # method self.learners = [] def select_correct(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_wrong(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(2, n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_none(self): self.tableview.selectionModel().clear() def cell_clicked(self, model_index): i, j = model_index.row(), model_index.column() if not i or not j: return n = self.tablemodel.rowCount() index = self.tablemodel.index selection = None if i == j == 1 or i == j == n - 1: selection = QItemSelection(index(2, 2), index(n - 1, n - 1)) elif i in (1, n - 1): selection = QItemSelection(index(2, j), index(n - 1, j)) elif j in (1, n - 1): selection = QItemSelection(index(i, 2), index(i, n - 1)) if selection is not None: self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def commit(self): if self.results is not None and self.data is not None \ and self.selected_learner: indices = self.tableview.selectedIndexes() indices = {(ind.row() - 2, ind.column() - 2) for ind in indices} actual = self.results.actual selected_learner = self.selected_learner[0] learner_name = self.learners[selected_learner] predicted = self.results.predicted[selected_learner] selected = [ i for i, t in enumerate(zip(actual, predicted)) if t in indices ] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values) metas = metas + (var, ) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[selected_learner, selected] extra.append(numpy.array(probs, dtype=object)) pvars = [ Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values ] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] row_ids = self.data.ids[row_indices] M = numpy.hstack((M, ) + tuple(extra)) domain = Orange.data.Domain(self.data.domain.attributes, self.data.domain.class_vars, metas) data = Orange.data.Table.from_numpy(domain, X, Y, M) data.ids = row_ids data.name = learner_name else: data = None self.send("Selected Data", data) def _invalidate(self): self.commit() def _learner_changed(self): # The selected learner has changed indices = self.tableview.selectedIndexes() self._update() selection = QItemSelection() for sel in indices: selection.select(sel, sel) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) self.commit() def _update(self): # Update the displayed confusion matrix if self.results is not None and self.selected_learner: index = self.selected_learner[0] cmatrix = confusion_matrix(self.results, index) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) total = rowsum.sum() if self.selected_quantity == 0: value = lambda i, j: int(cmatrix[i, j]) elif self.selected_quantity == 1: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i]) if colsum[i] else "N/A") elif self.selected_quantity == 2: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i]) if colsum[i] else "N/A") else: assert False for i, row in enumerate(cmatrix): for j, _ in enumerate(row): item = self._item(i + 2, j + 2) item.setData(value(i, j), Qt.DisplayRole) item.setToolTip("actual: {}\npredicted: {}".format( self.headers[i], self.headers[j])) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self._set_item(i + 2, j + 2, item) model = self.tablemodel font = model.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) def sum_item(value): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) return item N = len(colsum) for i in range(N): model.setItem(N + 2, i + 2, sum_item(int(colsum[i]))) model.setItem(i + 2, N + 2, sum_item(int(rowsum[i]))) model.setItem(N + 2, N + 2, sum_item(int(total)))
class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setCentralWidget(self.ui.mangaTableView) self.newMangaDialog = NewMangaDialog() self.mangaDownloadDialog = MangaDownloadDialog() self.mangaTableModel = QStandardItemModel(0, 3, self) self.mangaTableModel.setHorizontalHeaderItem(0, QStandardItem(QString("Manga"))) self.mangaTableModel.setHorizontalHeaderItem(1, QStandardItem(QString("Latest Chapter"))) self.mangaTableModel.setHorizontalHeaderItem(2, QStandardItem(QString("Status"))) self.ui.mangaTableView.setModel(self.mangaTableModel) newMangaAction = QAction(QIcon("./icon/add.ico"),'New Manga', self) newMangaAction.setShortcut('Ctrl+N') newMangaAction.triggered.connect(self.newMangaDialog.show) removeMangaAction = QAction(QIcon("./icon/delete.ico"),'Remove Manga', self) removeMangaAction.setShortcut('Delete') preferencesAction = QAction(QIcon("./icon/preferences.ico"),'Preferences', self) aboutAction = QAction(QIcon("./icon/about.ico"),'About', self) self.ui.toolBar.addAction(newMangaAction) self.ui.toolBar.addAction(removeMangaAction) self.ui.toolBar.addSeparator() self.ui.toolBar.addAction(preferencesAction) self.ui.toolBar.addSeparator() self.ui.toolBar.addAction(aboutAction) self.progressBar = QProgressBar(self.ui.statusbar) self.ui.statusbar.addPermanentWidget(self.progressBar) self.progressBar.hide() def closeEvent(self, QCloseEvent): mangaList = [] for i in range(self.mangaTableModel.rowCount()): mangaList.append({ "name" : str(self.mangaTableModel.item(i, 0).text()), "latestChapter" : str(self.mangaTableModel.item(i, 1).text()), "status" : "Updated", "link" : "/trial.html" }) self.emit(SIGNAL("applicationClosed"),mangaList) def initializeProgressBar(self, size): self.progressBar.setRange(0, size) self.progressBar.setValue(0) self.progressBar.show() def updateProgressBar(self, value): self.progressBar.setValue(value) def updateStatusBar(self, msg): self.ui.statusbar.showMessage(msg) def updateMangaTable(self, chapter): isFound = False for i in range(self.mangaTableModel.rowCount()): mangaItem = self.mangaTableModel.item(i) if mangaItem.text() == chapter["name"]: self.mangaTableModel.item(i, 1).setText(chapter["latestChapter"]) self.mangaTableModel.item(i, 2).setText(chapter["status"]) isFound = True break if not isFound: self.addRowToMangaTable(chapter) def addMangaListToMangaTable(self, mangaList): for i in range(len(mangaList)): self.addRowToMangaTable(mangaList[i]) def addRowToMangaTable(self, manga): i = self.mangaTableModel.rowCount() mangaItem = QStandardItem(QString(manga["name"])) latestChapterItem = QStandardItem(QString(manga["latestChapter"])) statusItem = QStandardItem(QString(manga["status"])) brush = QBrush(QColor(255, 255, 255)) if i%2==0 else QBrush(QColor(200, 200, 200)) mangaItem.setBackground(brush) latestChapterItem.setBackground(brush) statusItem.setBackground(brush) self.mangaTableModel.setItem(i, 0, mangaItem) self.mangaTableModel.setItem(i, 1, latestChapterItem) self.mangaTableModel.setItem(i, 2, statusItem)
def _guiUpdate_metaTable(self,uuid): dbconn=DbConn() meta=dbconn.get_meta_kv() stream=meta[str(uuid)] print stream model=QStandardItemModel() model.setHorizontalHeaderItem(0,QStandardItem("Attribute")) model.setHorizontalHeaderItem(1,QStandardItem("Value")) while model.rowCount() > 0: model.removeRow(0) for k in stream.keys(): name=stream[k] # print name # print k item1 = QStandardItem(k) item2 = QStandardItem(name) # item=QTableWidgetItem() # item.setText(1,name) # item.setText(2,k) # self.ui.metaEditor # model.appendRow([item1,item2]) # self.ui.metaEditor.appendI model.appendRow([item1,item2]) self.ui.metaEditor.setModel(model) # self.ui.metaEditor.addTopLevelItem(item) # self.ui.metaEditor. # model.itemChanged.connect(lambda: on_item_changed()) self.metamodel=model # self.ui.met self.ui.metaEditor.setModel(model) # self.ui.metaEditor.setEditTriggers(QAbstractItemView.NoEditTriggers) # self.ui.metaEditor.sortByColumn(1) self.ui.metaEditor.resizeColumnsToContents()