def data(self, index, role=Qt.DisplayRole): if index.column() is 1 and role == Qt.ToolTipRole: isOwn = index.data(self.OWN_MESSAGE_ROLE).toBool() toolTip = convert_string(index.data(self.TOOL_TIP_MSG_ROLE).toString()) messageTime, _ = index.data(self.MESSAGE_TIME_ROLE).toDouble() recvTime, _ = index.data(self.RECV_TIME_ROLE).toDouble() return self._createToolTipText(isOwn, toolTip, messageTime, recvTime) return QStandardItemModel.data(self, index, role)
def setData(self, index, value, role): """ \reimp Set the data which value is `value` at index `index` with role `role`. \return `True` if no error occured, `False` otherwise. """ if self.ch == True: if role == Qt.CheckStateRole: ret = QStandardItemModel.setData(self, index, value, role) if ret == False: return False data = QStandardItemModel.data(self, index, Qt.UserRole + 1) if not data.isValid(): return False self.emit(SIGNAL("stateChanged"), index) return True
def setData(self, index, value, role): """ \reimp Set the data which value is `value` at index `index` with role `role`. \return `True` if no error occured, `False` otherwise. """ if self.ch == True: if role == Qt.CheckStateRole: ret = QStandardItemModel.setData(self, index, value, role) if ret == False: return False data = QStandardItemModel.data(self, index, Qt.UserRole + 1) if not data.isValid(): return False self.emit(SIGNAL("stateChanged"), index) return True #return true if ok
class Emotion(QtGui.QWidget): EMOTION_DIR = "./resource/expression" WIDTH = 460 HEIGHT = 300 selectChanged = pyqtSignal(str) def __init__(self,parent=None):# super(Emotion,self).__init__(parent) super(Emotion,self).setWindowFlags(QtCore.Qt.Popup) self.resize(QSize(Emotion.WIDTH,Emotion.HEIGHT)) self.setWindowTitle("表情選擇") #self.setModal(True) #self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) self.emotion_initial() def emotion_initial(self): self.emotion_table = QTableView() self.emotion_table.horizontalHeader().setVisible(False) self.emotion_table.verticalHeader().setVisible(False) self.emotion_table.setMouseTracking(True) self.emotion_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.emotion_table.verticalHeader().setDefaultSectionSize(30) self.emotion_table.horizontalHeader().setDefaultSectionSize(30) self.emotion_table.setIconSize(QSize(30,30)) self.emotion_table.entered.connect(self.showEmotionTips) self.emotion_model = QStandardItemModel() emotions = os.listdir(Emotion.EMOTION_DIR) i = 0 emotions_size = len(emotions) emotions = sorted(emotions,cmp=emotioncmp) while i < emotions_size: self.add_emotion(emotions[i:i+14]) i = i + 14 self.emotion_table.setModel(self.emotion_model) self.emotion_table.clicked.connect(self.emotion_click) # mainLayout=QVBoxLayout() mainLayout.addWidget(self.emotion_table) self.setLayout(mainLayout) #self. def showEmotionTips(self,index): if index.isValid(): QToolTip.showText(QCursor.pos(), "Hello", None) def add_emotion(self,emotions): ''' :param emotions a list of emotion will be adding to emotion table ''' cells = [] for emotion in emotions: item = QtGui.QStandardItem(QIcon(os.path.join(Emotion.EMOTION_DIR,emotion)),emotion) cells.append(item) self.emotion_model.appendRow(cells) #def eventFilter(self, event): #p = QCursor.pos() - self.pos() #item = self.emotion_table def emotion_click(self): row = self.emotion_table.currentIndex().row() column = self.emotion_table.currentIndex().column() #self.accept() self.close() self.selectChanged.emit(self.get_selected_emotion(row,column)) def get_selected_emotion(self,row,column): emotion = self.emotion_model.data(self.emotion_model.index(row, column)) if emotion: return str(emotion.toString()) else: return "N/A"
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()
def data(self, index, role): """ \reimp Nodes' pointers are encapsulated in QStandardItem (role : Qt.UserRole + 1). Most of the data can only be retrieved only if the node is retrieved: * The node name * The node icon * ... To do so, the TreeModel.data() method calls the QStandardItemModel.data() method by passing the `index` parameter and `Qt.UserRole + 1` or `Qt.UserRole + 2` to it. In the second case, it retrieves a boolean used to know if the node is already expended and returns directly. \param index the index of the data we want to get \param role the role of the data we want to retrieve \return a QVariant containing the data, or an invalid QVariant if the data could not be retrieved. """ if not index.isValid(): return QVariant() # Qt.UserRole + 2 contain a boolean indicating if the node has already been expanded # in the tree. if role == Qt.UserRole + 3: return QStandardItemModel.data(self, index, role) if role == Qt.UserRole + 2: return QStandardItemModel.data(self, index, role) # call QStandardItemModel.data method with a Qt.UserRole + 1 to get the pointer on the node # (returns a invalid QVariant if the node or the data is None) data = QStandardItemModel.data(self, index, Qt.UserRole + 1) if not data.isValid(): return data # getting the node or returning an invalid QVariant() if the node is not valid uid, valid = data.toULongLong() if not valid: return QVariant() node = self.VFS.getNodeById(uid) if node is None: return QVariant() # if role == UserRole + 1, it means that the node itself must be returned (the pointer # on the node, encapsulated in a QVariant() if role == (Qt.UserRole + 1): return data # in other cases, returns the requires data : icon, color, etc. or an invalid QVariant() # if the role does not correpond to anything. if role == Qt.DisplayRole: display = QString.fromUtf8(node.name()) if self.displayCount: display += QString(" (" + str(node.totalChildrenCount()) + ")") return QVariant(display) if role == Qt.DecorationRole: pixmap = QPixmap(node.icon()) if node.hasChildren(): try: pfsobj = node.children()[0].fsobj( ).this #XXX fsobj have uid now except AttributeError: pfsobj = None try: nfsobj = node.fsobj().this except AttributeError: nfsobj = None if pfsobj != nfsobj: pixmap = pixmap.scaled(QSize(128, 128), Qt.KeepAspectRatio) painter = QPainter(pixmap) rootPixmap = QPixmap(":root") painter.drawPixmap(0, 0, rootPixmap) painter.end() return QVariant(QIcon(pixmap)) if role == Qt.BackgroundRole: if index == self.currentIndex: palette = QPalette().color(QPalette.Highlight) return QVariant(QColor(palette)) if role == Qt.ForegroundRole: if (index == self.currentIndex) and not node.isDeleted(): palette = QPalette().color(QPalette.HighlightedText) return QVariant(QColor(palette)) if node.isDeleted(): return QVariant(QColor(Qt.red)) if self.ch == True: if role == Qt.CheckStateRole: if index.column() == 0: if node.uid() in self.selection.get(): return Qt.Checked else: return Qt.Unchecked return QVariant()
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 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
def data(self, index, role): """ \reimp Nodes' pointers are encapsulated in QStandardItem (role : Qt.UserRole + 1). Most of the data can only be retrieved only if the node is retrieved: * The node name * The node icon * ... To do so, the TreeModel.data() method calls the QStandardItemModel.data() method by passing the `index` parameter and `Qt.UserRole + 1` or `Qt.UserRole + 2` to it. In the second case, it retrieves a boolean used to know if the node is already expended and returns directly. \param index the index of the data we want to get \param role the role of the data we want to retrieve \return a QVariant containing the data, or an invalid QVariant if the data could not be retrieved. """ if not index.isValid(): return QVariant() # Qt.UserRole + 2 contain a boolean indicating if the node has already been expanded # in the tree. if role == Qt.UserRole + 2: return QStandardItemModel.data(self, index, role) # get the checkstate if necessary if self.ch == True: if role == Qt.CheckStateRole: data = QStandardItemModel.data(self, index, Qt.CheckStateRole) if data == Qt.Checked: return Qt.Checked elif data == Qt.PartiallyChecked: return Qt.Checked else: return Qt.Unchecked # call QStandardItemModel.data method with a Qt.UserRole + 1 to get the pointer on the node # (returns a invalid QVariant if the node or the data is None) data = QStandardItemModel.data(self, index, Qt.UserRole + 1) if not data.isValid(): return data # getting the node or returning an invalid QVariant() if the node is not valid node = self.VFS.getNodeFromPointer(data.toULongLong()[0]) if node == None: return QVariant() # if role == UserRole + 1, it means that the node itself must be returned (the pointer # on the node, encapsulated in a QVariant() if role == (Qt.UserRole + 1): return data # in other cases, returns the requires data : icon, color, etc. or an invalid QVariant() # if the role does not correpond to anything. if role == Qt.ForegroundRole: if node.isDeleted(): return QVariant(QColor(Qt.red)) if role == Qt.DisplayRole : return QVariant(QString.fromUtf8(node.name())) if role == Qt.DecorationRole: return QVariant(QIcon(node.icon())) return QVariant()
item1 = QStandardItem() item1.setText("B") pixmap1 = QPixmap(50, 50) pixmap1.fill(Qt.blue) item1.setIcon(QIcon(pixmap1)) item1.setToolTip("indexB") parentItem.appendRow(item1) # 创建新的标准项,这里使用了另一种方法来设置文本、图标和工具提示 item2 = QStandardItem() pixmap2 = QPixmap(50, 50) pixmap2.fill(Qt.green) item2.setData("C", Qt.EditRole) # 等同于 setText("C") item2.setData("indexC", Qt.ToolTipRole) # 等同于 setToolTip("indexB") item2.setData(QIcon(pixmap2), Qt.DecorationRole) #等同于 setIcon(QIcon(pixmap1)) parentItem.appendRow(item2) # 在树视图中显示模型 view.setModel(model) view.show() # 获取item0的索引并输出item0的子项数目,然后输出了item1的显示文本和工具提示 indexA = model.index(0, 0, QModelIndex()) print "indexA row count: ", model.rowCount(indexA) indexB = model.index(0, 0, indexA) print "indexB text: ", model.data(indexB, Qt.EditRole).toString() print "indexB toolTip: ", model.data(indexB, Qt.ToolTipRole).toString() app.exec_()
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
def data(self, index, role): """ \reimp Nodes' pointers are encapsulated in QStandardItem (role : Qt.UserRole + 1). Most of the data can only be retrieved only if the node is retrieved: * The node name * The node icon * ... To do so, the TreeModel.data() method calls the QStandardItemModel.data() method by passing the `index` parameter and `Qt.UserRole + 1` or `Qt.UserRole + 2` to it. In the second case, it retrieves a boolean used to know if the node is already expended and returns directly. \param index the index of the data we want to get \param role the role of the data we want to retrieve \return a QVariant containing the data, or an invalid QVariant if the data could not be retrieved. """ if not index.isValid(): return QVariant() # Qt.UserRole + 2 contain a boolean indicating if the node has already been expanded # in the tree. if role == Qt.UserRole + 3: return QStandardItemModel.data(self, index, role) if role == Qt.UserRole + 2: return QStandardItemModel.data(self, index, role) # call QStandardItemModel.data method with a Qt.UserRole + 1 to get the pointer on the node # (returns a invalid QVariant if the node or the data is None) data = QStandardItemModel.data(self, index, Qt.UserRole + 1) if not data.isValid(): return data # getting the node or returning an invalid QVariant() if the node is not valid node = self.VFS.getNodeFromPointer(data.toULongLong()[0]) if node == None: return QVariant() # if role == UserRole + 1, it means that the node itself must be returned (the pointer # on the node, encapsulated in a QVariant() if role == (Qt.UserRole + 1): return data # in other cases, returns the requires data : icon, color, etc. or an invalid QVariant() # if the role does not correpond to anything. if role == Qt.DisplayRole : return QVariant(QString.fromUtf8(node.name())) if role == Qt.DecorationRole: pixmap = QPixmap(node.icon()) if node.hasChildren(): try: pfsobj = node.children()[0].fsobj().this except AttributeError: pfsobj = None try: nfsobj = node.fsobj().this except AttributeError: nfsobj = None if pfsobj != nfsobj: pixmap = pixmap.scaled(QSize(128, 128), Qt.KeepAspectRatio) painter = QPainter(pixmap) rootPixmap = QPixmap(":root") painter.drawPixmap(0, 0, rootPixmap) painter.end() return QVariant(QIcon(pixmap)) if role == Qt.BackgroundRole: if index == self.currentIndex: palette = QPalette().color(QPalette.Highlight) return QVariant(QColor(palette)) if role == Qt.ForegroundRole: if (index == self.currentIndex) and not node.isDeleted(): palette = QPalette().color(QPalette.HighlightedText) return QVariant(QColor(palette)) if node.isDeleted(): return QVariant(QColor(Qt.red)) if self.ch == True: if role == Qt.CheckStateRole: if index.column() == 0: if long(node.this) in self.selection.get(): return Qt.Checked else: return Qt.Unchecked return QVariant()