def create_actions(self): self.change_color_action = QtGui.QAction("Change &color", self) self.change_color_action.triggered.connect(self.change_color_callback) self.add_group_action = QtGui.QAction("&Add group", self) self.add_group_action.triggered.connect(self.add_group_callback) self.rename_channel_group_action = QtGui.QAction("Re&name group", self) self.rename_channel_group_action.setShortcut("F2") self.rename_channel_group_action.triggered.connect( self.rename_channel_group_callback) self.rename_channel_action = QtGui.QAction("Rename c&hannel", self) self.rename_channel_action.setShortcut("F3") self.rename_channel_action.triggered.connect( self.rename_channel_callback) self.remove_group_action = QtGui.QAction("&Remove group", self) self.remove_group_action.triggered.connect(self.remove_group_callback) # Add actions to the widget. self.addAction(self.change_color_action) self.addAction(self.add_group_action) self.addAction(self.rename_channel_group_action) self.addAction(self.rename_channel_action) self.addAction(self.remove_group_action)
def create_layout(self): self.setStyleSheet(DOCKSTYLESHEET) # Create the title layout. self.setContentsMargins(0, 0, 0, 0) box = QtGui.QHBoxLayout() box.setContentsMargins(0, 2, 0, 2) box.setSpacing(0) # Add the title. self.title_widget = QtGui.QLabel(self.name, self) box.addSpacing(5) box.addWidget(self.title_widget) # Add spacing. box.addStretch(1000) # Add the dock-related buttons. if self.is_floatable(): box.addWidget(self.dockable_button) box.addWidget(self.maximize_button) box.addWidget(self.dock_button) # Add the close button. if self.is_closable(): box.addWidget(self.close_button) self.setLayout(box)
def force_key_release(self): """HACK: force release of Ctrl, Shift and Alt when focus out.""" self.keyReleaseEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyRelease, QtCore.Qt.Key_Control, QtCore.Qt.NoModifier)) self.keyReleaseEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyRelease, QtCore.Qt.Key_Shift, QtCore.Qt.NoModifier)) self.keyReleaseEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyRelease, QtCore.Qt.Key_Alt, QtCore.Qt.NoModifier))
def create_color_dialog(self): self.color_dialog = QtGui.QColorDialog(self) self.color_dialog.setOptions(QtGui.QColorDialog.DontUseNativeDialog) for i in xrange(48): if i < len(COLORMAP): rgb = COLORMAP[i] * 255 else: rgb = (255, 255, 255) # rgb = (1., 1., 1.) k = 6 * (np.mod(i, 8)) + i // 8 self.color_dialog.setStandardColor(k, QtGui.qRgb(*rgb))
def __init__(self, parent=None, getfocus=None): super(LogView, self).__init__(parent) # Create the text edit widget. self.textedit = QtGui.QTextEdit() self.textedit.setReadOnly(True) # Add the text edit widget to the layout. box = QtGui.QVBoxLayout() box.addWidget(self.textedit) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box)
def create_layout(self): self.projection_view = ProjectionView(self, getfocus=False) self.feature_view = FeatureView(self, getfocus=False) self.set_data() # Connect the FeatureView signal to the top-level widget signals. self.feature_view.spikesHighlighted.connect(self.spikesHighlighted) self.feature_view.spikesSelected.connect(self.spikesSelected) # Connect the bottom-level projectionChanged signals to the top-level # widget signals. self.feature_view.projectionChanged.connect(self.projectionChanged) self.projection_view.projectionChanged.connect(self.projectionChanged) # Interconnect the projectionChanged between the two bottom-level widgets. self.projection_view.projectionChanged.connect( self.projection_changed_projection_callback) self.feature_view.projectionChanged.connect( self.projection_changed_feature_callback) box = QtGui.QVBoxLayout() # HACK: pyside does not have this function if hasattr(box, 'setMargin'): box.setMargin(0) box.addWidget(self.projection_view) box.addWidget(self.feature_view) self.setLayout(box)
def __init__(self, parent=None, getfocus=None): super(IPythonView, self).__init__(parent) # Create an in-process kernel self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.shell = self.kernel.shell self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.control = RichIPythonWidget() self.control.set_default_style(colors='linux') self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(self.stop) # Enable Pylab mode. self.shell.enable_pylab() self.shell.automagic = True # Add some variables in the namespace. self.push(galry=galry) box = QtGui.QVBoxLayout() box.addWidget(self.control) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box)
def shortcuts_callback(self, checked=None): e = QtGui.QKeyEvent( QtCore.QEvent.KeyPress, QtCore.Qt.Key_H, QtCore.Qt.NoModifier, ) self.keyPressEvent(e)
def set_data(self, fetdim=None, nchannels=None, nextrafet=None, channels=None): if fetdim is None: fetdim = 3 if nchannels is None: nchannels = 1 if nextrafet is None: nextrafet = 0 if channels is None: channels = range(nchannels) # No need to update the widget if the data has not changed. if not self._has_changed(fetdim, nchannels, nextrafet): return self.fetdim = fetdim self.nchannels = nchannels self.channels = channels self.nextrafet = nextrafet # Remove the existing layout. if self.layout(): QtGui.QWidget().setLayout(self.layout()) self.box = self.create_widget() self.setLayout(self.box)
def create_save_progress_dialog(self): self.save_progress = QtGui.QProgressDialog("Saving...", "Cancel", 0, 0, self, QtCore.Qt.Tool) self.save_progress.setWindowModality(QtCore.Qt.WindowModal) self.save_progress.setValue(0) self.save_progress.setWindowTitle('Saving') self.save_progress.setCancelButton(None) self.save_progress.setMinimumDuration(0)
def create_open_progress_dialog(self): self.open_progress = QtGui.QProgressDialog("Converting to Kwik...", "Cancel", 0, 0, self, QtCore.Qt.Tool) self.open_progress.setWindowModality(QtCore.Qt.WindowModal) self.open_progress.setValue(0) self.open_progress.setWindowTitle('Loading') self.open_progress.setCancelButton(None) self.open_progress.setMinimumDuration(0)
def get_icon(name): """Get an icon from the icons folder in the current package, or directly from galry.""" path = os.path.dirname(os.path.realpath(__file__)) path = os.path.join(path, "../icons/%s.png" % name) if not os.path.exists(path): return galry.get_icon(name) else: return QtGui.QIcon(path)
def add_button(self, name, text, callback=None, shortcut=None, checkable=False, icon=None): # Creation action. action = QtGui.QAction(text, self) if callback is None: callback = getattr(self, name + '_callback', None) if callback: action.triggered.connect(callback) if shortcut: action.setShortcut(shortcut) if icon: action.setIcon(get_icon(icon)) action.setCheckable(checkable) # Create button button = QtGui.QToolButton(self) button.setContentsMargins(*((5,)*4)) button.setDefaultAction(action) return button
def create_context_menu(self): self.create_color_dialog() self.context_menu = QtGui.QMenu(self) self.context_menu.addAction(self.change_color_action) self.context_menu.addSeparator() self.context_menu.addAction(self.add_group_action) self.context_menu.addAction(self.rename_channel_group_action) self.context_menu.addAction(self.rename_channel_action) self.context_menu.addAction(self.remove_group_action)
def create_feature_widget(self, coord=0): # coord => (channel, feature) self.projection = [(0, 0), (0, 1)] hbox = QtGui.QHBoxLayout() hbox.setSpacing(0) # HACK: pyside does not have this function if hasattr(hbox, 'setMargin'): hbox.setMargin(0) # channel selection comboBox = QtGui.QComboBox(self) comboBox.setEditable(True) comboBox.setMaximumWidth(100) comboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) comboBox.addItems(["%d" % i for i in self.channels]) comboBox.addItems(["Extra %d" % i for i in xrange(self.nextrafet)]) comboBox.editTextChanged.connect(partial(self.select_channel, coord)) # comboBox.setFocusPolicy(QtCore.Qt.ClickFocus) self.channel_box[coord] = comboBox hbox.addWidget(comboBox) # create 3 buttons for selecting the feature widths = [30] * self.fetdim labels = ['PC%d' % i for i in xrange(1, self.fetdim + 1)] hbox.addSpacing(10) # ensure exclusivity of the group of buttons pushButtonGroup = QtGui.QButtonGroup(self) for i in xrange(len(labels)): # selecting feature i pushButton = QtGui.QPushButton(labels[i], self) pushButton.setCheckable(True) if coord == i: pushButton.setChecked(True) pushButton.setMaximumSize(QtCore.QSize(widths[i], 20)) pushButton.clicked.connect(partial(self.select_feature, coord, i)) pushButtonGroup.addButton(pushButton, i) self.feature_buttons[coord][i] = pushButton hbox.addWidget(pushButton) return hbox
def create_widget(self): box = QtGui.QHBoxLayout() if hasattr(box, 'setMargin'): box.setContentsMargins(QtCore.QMargins(10, 2, 10, 2)) # box.addSpacing(10) # coord => channel combo box self.channel_box = [None, None] # coord => (butA, butB, butC) self.feature_buttons = [[None] * self.fetdim, [None] * self.fetdim] # add feature widget self.feature_widget1 = self.create_feature_widget(0) box.addLayout(self.feature_widget1) box.addSpacing(10) # Switch button. # button = QtGui.QPushButton('Flip', self) button = QtGui.QPushButton(self) button.setIcon(get_icon('flip')) button.setMaximumWidth(40) button.clicked.connect(self.flip_projections_callback) box.addWidget(button) box.addSpacing(10) # add feature widget self.feature_widget2 = self.create_feature_widget(1) box.addLayout(self.feature_widget2) # box.addSpacing(10) self.setTabOrder(self.channel_box[0], self.channel_box[1]) # self.setMaximumWidth(300) # self.setMaximumHeight(80) return box
def create_context_menu(self): self.create_color_dialog() self.context_menu = QtGui.QMenu(self) self.context_menu.addAction(self.change_color_action) self.context_menu.addSeparator() self.context_menu.addAction(self.move_to_noise_action) self.context_menu.addAction(self.move_to_mua_action) self.context_menu.addAction(self.move_to_good_action) self.context_menu.addSeparator() self.context_menu.addAction(self.add_group_action) self.context_menu.addAction(self.rename_group_action) self.context_menu.addAction(self.remove_group_action)
def add_action(self, name, text, callback=None, shortcut=None, checkable=False, checked=False, icon=None): action = QtGui.QAction(text, self) if callback is None: callback = getattr(self, name + '_callback', None) if callback: action.triggered.connect(callback) if shortcut: action.setShortcut(shortcut) if icon: action.setIcon(get_icon(icon)) action.setCheckable(checkable) action.setChecked(checked) setattr(self, name + '_action', action)
def data(self, index, role): item = index.internalPointer() col = index.column() # group item if type(item) == GroupItem: if col == 0: if role == QtCore.Qt.DisplayRole: return str(item.name()) # color elif col == self.columnCount() - 1: if role == QtCore.Qt.BackgroundRole: if item.color() >= 0: color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(*color) elif role == QtCore.Qt.DisplayRole: return "" # channel item if type(item) == ChannelItem: # name if col == 0: if role == QtCore.Qt.DisplayRole: return str(item.name()) elif role == QtCore.Qt.BackgroundRole: if item.bgcolor is None: return elif item.bgcolor == 'candidate': color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 90) elif item.bgcolor == 'target': # return QtGui.QColor(177, 177, 177, 255) color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 255) elif role == QtCore.Qt.ForegroundRole: if item.bgcolor is None: return QtGui.QColor(177, 177, 177, 255) elif item.bgcolor == 'target': return QtGui.QColor(0, 0, 0, 255) # color elif col == self.columnCount() - 1: if role == QtCore.Qt.BackgroundRole: color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(*color) # default if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: return item.data(col) if role == QtCore.Qt.ForegroundRole: return QtGui.QColor(177, 177, 177, 255)
def select(self, channels, groups=None, wizard=False): """Select multiple channels from their indices.""" self.wizard = wizard if channels is None: channels = [] if groups is None: groups = [] if isinstance(channels, (int, long, np.integer)): channels = [channels] if isinstance(groups, (int, long, np.integer)): groups = [groups] if len(channels) == len(groups) == 0: return # Convert to lists. channels = list(channels) groups = list(groups) selection_model = self.selectionModel() selection = QtGui.QItemSelection() # Select groups. for groupidx in groups: group = self.model.get_group(groupidx) if group is not None: selection.select(group.index, group.index) # Select channels. for channelidx in channels: channel = self.model.get_channel(channelidx) if channel is not None: selection.select(channel.index, channel.index) # Process selection. selection_model.select(selection, selection_model.Clear | selection_model.Current | selection_model.Select | selection_model.Rows ) if len(channels) > 0: channel = self.model.get_channel(channels[-1]) if channel is not None: # Set current index in the selection. selection_model.setCurrentIndex( channel.index, QtGui.QItemSelectionModel.NoUpdate) # Scroll to that channel. self.scrollTo(channel.index)
def change_color_callback(self, checked=None): item = self.current_item initial_color = item.color() if initial_color >= 0: initial_color = 255 * COLORMAP[initial_color] initial_color = QtGui.QColor(*initial_color) color = QtGui.QColorDialog.getColor(initial_color) else: color = QtGui.QColorDialog.getColor() # return if the user canceled if not color.isValid(): return # get the RGB values of the chosen color rgb = np.array(color.getRgbF()[:3]).reshape((1, -1)) # take the closest color in the palette color = np.argmin(np.abs(COLORMAP[1:, :] - rgb).sum(axis=1)) + 1 # Change the color and emit the signal. if isinstance(item, ChannelItem): self.change_channel_color(item.channelidx(), color) elif isinstance(item, GroupItem): self.change_group_color(item.groupidx(), color)
def create_actions(self): self.change_color_action = QtGui.QAction("Change &color", self) self.change_color_action.triggered.connect(self.change_color_callback) self.add_group_action = QtGui.QAction("&Add group", self) self.add_group_action.triggered.connect(self.add_group_callback) self.rename_group_action = QtGui.QAction("Re&name group", self) self.rename_group_action.setShortcut("F2") self.rename_group_action.triggered.connect(self.rename_group_callback) self.remove_group_action = QtGui.QAction("&Remove group", self) self.remove_group_action.triggered.connect(self.remove_group_callback) self.move_to_mua_action = QtGui.QAction("Move to &MUA", self) self.move_to_mua_action.setShortcut("Delete") self.move_to_mua_action.setIcon(get_icon('multiunit')) self.move_to_mua_action.triggered.connect(self.move_to_mua_callback) self.move_to_noise_action = QtGui.QAction("Move to &noise", self) self.move_to_noise_action.setShortcut('Shift+Delete') self.move_to_noise_action.setIcon(get_icon('noise')) self.move_to_noise_action.triggered.connect( self.move_to_noise_callback) self.move_to_good_action = QtGui.QAction("Move to &good", self) # self.move_to_good_action.setIcon(get_icon('noise')) self.move_to_good_action.triggered.connect(self.move_to_good_callback) # Add actions to the widget. self.addAction(self.change_color_action) self.addAction(self.add_group_action) self.addAction(self.rename_group_action) self.addAction(self.remove_group_action) self.addAction(self.move_to_noise_action) self.addAction(self.move_to_mua_action) self.addAction(self.move_to_good_action)
def __init__(self, parent=None, dolog=True, filename=None): super(KwikSkope, self).__init__(parent) # HACK: display the icon in Windows' taskbar. if os.name == 'nt': try: import ctypes myappid = 'klustateam.kwikskope' ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( myappid) except: pass self.dolog = dolog if self.dolog: create_file_logger() log.debug("Using {0:s}.".format(QT_BINDING)) # Main window options. self.move(50, 50) self.setWindowTitle('KwikSkope') # Focus options. self.setFocusPolicy(QtCore.Qt.WheelFocus) self.setMouseTracking(True) # Dock widgets options. self.setDockNestingEnabled(True) self.setAnimated(False) self.setWindowIcon(get_icon('logo')) # Initialize some variables. # self.statscache = None # self.loader = KlustersLoader() self.loader = HDF5Loader() self.loader.progressReported.connect(self.open_progress_reported) self.loader.saveProgressReported.connect(self.save_progress_reported) self.wizard = Wizard() self.controller = None self.spikes_highlighted = [] self.spikes_selected = [] self._wizard = False self.is_file_open = False self.need_save = False self.busy_cursor = QtGui.QCursor(QtCore.Qt.BusyCursor) self.normal_cursor = QtGui.QCursor(QtCore.Qt.ArrowCursor) self.is_busy = False self.override_color = False self.computing_correlograms = False self.computing_matrix = False # Create the main window. self.create_views() self.create_file_actions() self.create_edit_actions() self.create_view_actions() self.create_help_actions() self.create_menu() self.create_toolbar() self.create_open_progress_dialog() self.create_save_progress_dialog() self.create_threads() # Update action enabled/disabled property. self.update_action_enabled() # Show the main window. self.set_styles() self.restore_geometry() # Automatically load a file upon startup if requested. if filename: filename = os.path.realpath(filename) self.open_task.open(self.loader, filename) self.show()
def data(self, index, role): item = index.internalPointer() col = index.column() # group item if type(item) == GroupItem: if col == 0: if role == QtCore.Qt.DisplayRole: return str(item.name()) # quality elif col == 1: if role == QtCore.Qt.TextAlignmentRole: return QtCore.Qt.AlignRight if role == QtCore.Qt.DisplayRole: return #"%." % item.quality() # spkcount elif col == 2: if role == QtCore.Qt.TextAlignmentRole: return QtCore.Qt.AlignRight if role == QtCore.Qt.DisplayRole: return str(item.spkcount()) # color elif col == self.columnCount() - 1: if role == QtCore.Qt.BackgroundRole: if item.color() >= 0: color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(*color) elif role == QtCore.Qt.DisplayRole: return "" # cluster item if type(item) == ClusterItem: # clusteridx if col == 0: if role == QtCore.Qt.DisplayRole: return str(item.clusteridx()) elif role == QtCore.Qt.BackgroundRole: if item.bgcolor is None: return elif item.bgcolor == 'candidate': color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 90) elif item.bgcolor == 'target': # return QtGui.QColor(177, 177, 177, 255) color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 255) elif role == QtCore.Qt.ForegroundRole: if item.bgcolor is None: return QtGui.QColor(177, 177, 177, 255) elif item.bgcolor == 'target': return QtGui.QColor(0, 0, 0, 255) # quality elif col == 1: if role == QtCore.Qt.TextAlignmentRole: return QtCore.Qt.AlignRight elif role == QtCore.Qt.DisplayRole: return "%.3f" % item.quality() elif role == QtCore.Qt.BackgroundRole: if item.bgcolor is None: return elif item.bgcolor == 'candidate': color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 90) elif item.bgcolor == 'target': color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 255) # return QtGui.QColor(177, 177, 177, 255) elif role == QtCore.Qt.ForegroundRole: if item.bgcolor is None: return QtGui.QColor(177, 177, 177, 255) elif item.bgcolor == 'target': return QtGui.QColor(0, 0, 0, 255) # spkcount elif col == 2: if role == QtCore.Qt.TextAlignmentRole: return QtCore.Qt.AlignRight if role == QtCore.Qt.DisplayRole: return "%d" % item.spkcount() elif role == QtCore.Qt.BackgroundRole: if item.bgcolor is None: return elif item.bgcolor == 'candidate': color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 90) elif item.bgcolor == 'target': # return QtGui.QColor(177, 177, 177, 255) color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(color[0], color[1], color[2], 255) elif role == QtCore.Qt.ForegroundRole: if item.bgcolor is None: return QtGui.QColor(177, 177, 177, 255) elif item.bgcolor == 'target': return QtGui.QColor(0, 0, 0, 255) # color elif col == self.columnCount() - 1: if role == QtCore.Qt.BackgroundRole: color = np.array(COLORMAP[item.color()]) * 255 return QtGui.QColor(*color) # default if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: return item.data(col) if role == QtCore.Qt.ForegroundRole: return QtGui.QColor(177, 177, 177, 255)