class Editor(QFrame): # {{{ editing_done = pyqtSignal(object) def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.capture = 0 self.setFrameShape(self.StyledPanel) self.setFrameShadow(self.Raised) self._layout = l = QGridLayout(self) self.setLayout(l) self.header = QLabel('') l.addWidget(self.header, 0, 0, 1, 2) self.use_default = QRadioButton('') self.use_custom = QRadioButton(_('Custom')) l.addWidget(self.use_default, 1, 0, 1, 3) l.addWidget(self.use_custom, 2, 0, 1, 3) self.use_custom.toggled.connect(self.custom_toggled) off = 2 for which in (1, 2): text = _('&Shortcut:') if which == 1 else _('&Alternate shortcut:') la = QLabel(text) la.setStyleSheet('QLabel { margin-left: 1.5em }') l.addWidget(la, off+which, 0, 1, 3) setattr(self, 'label%d'%which, la) button = QPushButton(_('None'), self) button.clicked.connect(partial(self.capture_clicked, which=which)) button.keyPressEvent = partial(self.key_press_event, which=which) setattr(self, 'button%d'%which, button) clear = QToolButton(self) clear.setIcon(QIcon(I('clear_left.png'))) clear.clicked.connect(partial(self.clear_clicked, which=which)) setattr(self, 'clear%d'%which, clear) l.addWidget(button, off+which, 1, 1, 1) l.addWidget(clear, off+which, 2, 1, 1) la.setBuddy(button) self.done_button = doneb = QPushButton(_('Done'), self) l.addWidget(doneb, 0, 2, 1, 1) doneb.clicked.connect(lambda : self.editing_done.emit(self)) l.setColumnStretch(0, 100) self.custom_toggled(False) def initialize(self, shortcut, all_shortcuts): self.header.setText('<b>%s: %s</b>'%(_('Customize'), shortcut['name'])) self.all_shortcuts = all_shortcuts self.shortcut = shortcut self.default_keys = [QKeySequence(k, QKeySequence.PortableText) for k in shortcut['default_keys']] self.current_keys = list(shortcut['keys']) default = ', '.join([unicode(k.toString(k.NativeText)) for k in self.default_keys]) if not default: default = _('None') current = ', '.join([unicode(k.toString(k.NativeText)) for k in self.current_keys]) if not current: current = _('None') self.use_default.setText(_('Default: %(deflt)s [Currently not conflicting: %(curr)s]')% dict(deflt=default, curr=current)) if shortcut['set_to_default']: self.use_default.setChecked(True) else: self.use_custom.setChecked(True) for key, which in zip(self.current_keys, [1,2]): button = getattr(self, 'button%d'%which) button.setText(key.toString(key.NativeText)) def custom_toggled(self, checked): for w in ('1', '2'): for o in ('label', 'button', 'clear'): getattr(self, o+w).setEnabled(checked) def capture_clicked(self, which=1): self.capture = which button = getattr(self, 'button%d'%which) button.setText(_('Press a key...')) button.setFocus(Qt.OtherFocusReason) button.setStyleSheet('QPushButton { font-weight: bold}') def clear_clicked(self, which=0): button = getattr(self, 'button%d'%which) button.setText(_('None')) def key_press_event(self, ev, which=0): code = ev.key() if self.capture == 0 or code in (0, Qt.Key_unknown, Qt.Key_Shift, Qt.Key_Control, Qt.Key_Alt, Qt.Key_Meta, Qt.Key_AltGr, Qt.Key_CapsLock, Qt.Key_NumLock, Qt.Key_ScrollLock): return QWidget.keyPressEvent(self, ev) button = getattr(self, 'button%d'%which) button.setStyleSheet('QPushButton { font-weight: normal}') mods = int(ev.modifiers()) & ~Qt.KeypadModifier txt = unicode(ev.text()) if txt and txt.lower() == txt.upper(): # We have a symbol like ! or > etc. In this case the value of code # already includes Shift, so remove it mods &= ~Qt.ShiftModifier sequence = QKeySequence(code|mods) button.setText(sequence.toString(QKeySequence.NativeText)) self.capture = 0 dup_desc = self.dup_check(sequence) if dup_desc is not None: error_dialog(self, _('Already assigned'), unicode(sequence.toString(QKeySequence.NativeText)) + ' ' + _('already assigned to') + ' ' + dup_desc, show=True) self.clear_clicked(which=which) def dup_check(self, sequence): for sc in self.all_shortcuts: if sc is self.shortcut: continue for k in sc['keys']: if k == sequence: return sc['name'] @property def custom_keys(self): if self.use_default.isChecked(): return None ans = [] for which in (1, 2): button = getattr(self, 'button%d'%which) t = unicode(button.text()) if t == _('None'): continue ks = QKeySequence(t, QKeySequence.NativeText) if not ks.isEmpty(): ans.append(ks) return tuple(ans)
class Editor(QFrame): # {{{ editing_done = pyqtSignal(object) def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.capture = 0 self.setFrameShape(self.StyledPanel) self.setFrameShadow(self.Raised) self._layout = l = QGridLayout(self) self.setLayout(l) self.header = QLabel('') l.addWidget(self.header, 0, 0, 1, 2) self.use_default = QRadioButton('') self.use_custom = QRadioButton(_('Custom')) l.addWidget(self.use_default, 1, 0, 1, 3) l.addWidget(self.use_custom, 2, 0, 1, 3) self.use_custom.toggled.connect(self.custom_toggled) off = 2 for which in (1, 2): text = _('&Shortcut:') if which == 1 else _('&Alternate shortcut:') la = QLabel(text) la.setStyleSheet('QLabel { margin-left: 1.5em }') l.addWidget(la, off + which, 0, 1, 3) setattr(self, 'label%d' % which, la) button = QPushButton(_('None'), self) button.clicked.connect(partial(self.capture_clicked, which=which)) button.keyPressEvent = partial(self.key_press_event, which=which) setattr(self, 'button%d' % which, button) clear = QToolButton(self) clear.setIcon(QIcon(I('clear_left.png'))) clear.clicked.connect(partial(self.clear_clicked, which=which)) setattr(self, 'clear%d' % which, clear) l.addWidget(button, off + which, 1, 1, 1) l.addWidget(clear, off + which, 2, 1, 1) la.setBuddy(button) self.done_button = doneb = QPushButton(_('Done'), self) l.addWidget(doneb, 0, 2, 1, 1) doneb.clicked.connect(lambda: self.editing_done.emit(self)) l.setColumnStretch(0, 100) self.custom_toggled(False) def initialize(self, shortcut, all_shortcuts): self.header.setText('<b>%s: %s</b>' % (_('Customize'), shortcut['name'])) self.all_shortcuts = all_shortcuts self.shortcut = shortcut self.default_keys = [ QKeySequence(k, QKeySequence.PortableText) for k in shortcut['default_keys'] ] self.current_keys = list(shortcut['keys']) default = ', '.join( [unicode(k.toString(k.NativeText)) for k in self.default_keys]) if not default: default = _('None') current = ', '.join( [unicode(k.toString(k.NativeText)) for k in self.current_keys]) if not current: current = _('None') self.use_default.setText( _('Default: %(deflt)s [Currently not conflicting: %(curr)s]') % dict(deflt=default, curr=current)) if shortcut['set_to_default']: self.use_default.setChecked(True) else: self.use_custom.setChecked(True) for key, which in zip(self.current_keys, [1, 2]): button = getattr(self, 'button%d' % which) button.setText(key.toString(key.NativeText)) def custom_toggled(self, checked): for w in ('1', '2'): for o in ('label', 'button', 'clear'): getattr(self, o + w).setEnabled(checked) def capture_clicked(self, which=1): self.capture = which button = getattr(self, 'button%d' % which) button.setText(_('Press a key...')) button.setFocus(Qt.OtherFocusReason) button.setStyleSheet('QPushButton { font-weight: bold}') def clear_clicked(self, which=0): button = getattr(self, 'button%d' % which) button.setText(_('None')) def key_press_event(self, ev, which=0): code = ev.key() if self.capture == 0 or code in (0, Qt.Key_unknown, Qt.Key_Shift, Qt.Key_Control, Qt.Key_Alt, Qt.Key_Meta, Qt.Key_AltGr, Qt.Key_CapsLock, Qt.Key_NumLock, Qt.Key_ScrollLock): return QWidget.keyPressEvent(self, ev) button = getattr(self, 'button%d' % which) button.setStyleSheet('QPushButton { font-weight: normal}') mods = int(ev.modifiers()) & ~Qt.KeypadModifier txt = unicode(ev.text()) if txt and txt.lower() == txt.upper(): # We have a symbol like ! or > etc. In this case the value of code # already includes Shift, so remove it mods &= ~Qt.ShiftModifier sequence = QKeySequence(code | mods) button.setText(sequence.toString(QKeySequence.NativeText)) self.capture = 0 dup_desc = self.dup_check(sequence) if dup_desc is not None: error_dialog(self, _('Already assigned'), unicode(sequence.toString(QKeySequence.NativeText)) + ' ' + _('already assigned to') + ' ' + dup_desc, show=True) self.clear_clicked(which=which) def dup_check(self, sequence): for sc in self.all_shortcuts: if sc is self.shortcut: continue for k in sc['keys']: if k == sequence: return sc['name'] @property def custom_keys(self): if self.use_default.isChecked(): return None ans = [] for which in (1, 2): button = getattr(self, 'button%d' % which) t = unicode(button.text()) if t == _('None'): continue ks = QKeySequence(t, QKeySequence.NativeText) if not ks.isEmpty(): ans.append(ks) return tuple(ans)
def __init__(self, parentWidget, title='', label='', labelColumn=0, buttonList=[], checkedId=-1, setAsDefault=False, spanWidth=True, borders=True): """ Appends a PM_RadioButtonList widget to the bottom of I{parentWidget}, the Property Manager dialog or group box. @param parentWidget: The parent group box containing this widget. @type parentWidget: PM_GroupBox or PM_Dialog @param title: The group box title. @type title: str @param label: The label for the coordinate spinbox. @type label: str @param labelColumn: The column in the parentWidget's grid layout to which this widget's label will be added. The labelColum can only be E{0} or E{1} @type labelColumn: int @param buttonList: A list of I{button info lists}. There is one button info list for each radio button in the list. The button info list contains the following three items: 1). Button Id (int), 2). Button text (str), 3). Button tool tip (str). @type buttonList: list @param spanWidth: If True, the widget and its label will span the width of the group box. Its label will appear directly above the widget (unless the label is empty) and is left justified. @type spanWidth: bool (default False) @param borders: If true (default), this widget will have borders displayed. otherwise the won't be any outside borders around the set of radio buttons this class provides @type borders: boolean """ # Intializing label, labelColumn etc is needed before doing # PM_GroupBox.__init__. This is done so that # self.parentWidget.addPmWidget(self) done at the end of __init__ # works properly. # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a # groupbox is always appended as the 'last widget' when its # parentWidget is also a groupbox. This is due to other PM widgets #(e.g. PM_PushButton)add themselves to their parent widget in their #__init__ using self.parentWidget.addPmWidget(self). So doing the #same thing here. More general fix is needed in PM_GroupBox code # --Ninad 2007-11-14 (comment copied from PM_coordinateSpinBoxes) self.label = label self.labelColumn = labelColumn self.spanWidth = spanWidth if label: # Create this widget's QLabel. self.labelWidget = QLabel() self.labelWidget.setText(label) PM_GroupBox.__init__(self, parentWidget, title) # These are needed to properly maintain the height of the grid if # all buttons in a row are hidden via hide(). self.vBoxLayout.setMargin(0) self.vBoxLayout.setSpacing(0) self.buttonGroup = QButtonGroup() self.buttonGroup.setExclusive(True) self.parentWidget = parentWidget self.buttonList = buttonList if setAsDefault: self.setDefaultCheckedId(checkedId) self.buttonsById = {} self.buttonsByText = {} # Create radio button list from button info. for buttonInfo in buttonList: buttonId = buttonInfo[0] buttonText = buttonInfo[1] buttonToolTip = buttonInfo[2] button = QRadioButton(self) button.setText(buttonText) button.setToolTip(buttonToolTip) # Not working. button.setCheckable(True) if checkedId == buttonId: button.setChecked(True) self.buttonGroup.addButton(button, buttonId) self.vBoxLayout.addWidget(button) self.buttonsById[buttonId] = button self.buttonsByText[buttonText] = button if isinstance(self.parentWidget, PM_GroupBox): self.parentWidget.addPmWidget(self) else: #@@ Should self be added to self.parentWidget's widgetList? #don't know. Retaining old code -- Ninad 2008-06-23 self._widgetList.append(self) self._rowCount += 1 if not borders: #reset the style sheet so that there are no borders around the #radio button set this class provides. self.setStyleSheet(self._getAlternateStyleSheet())
def __init__(self, parentWidget, title = '', label = '', labelColumn = 0, buttonList = [], checkedId = -1, setAsDefault = False, spanWidth = True, borders = True ): """ Appends a PM_RadioButtonList widget to the bottom of I{parentWidget}, the Property Manager dialog or group box. @param parentWidget: The parent group box containing this widget. @type parentWidget: PM_GroupBox or PM_Dialog @param title: The group box title. @type title: str @param label: The label for the coordinate spinbox. @type label: str @param labelColumn: The column in the parentWidget's grid layout to which this widget's label will be added. The labelColum can only be E{0} or E{1} @type labelColumn: int @param buttonList: A list of I{button info lists}. There is one button info list for each radio button in the list. The button info list contains the following three items: 1). Button Id (int), 2). Button text (str), 3). Button tool tip (str). @type buttonList: list @param spanWidth: If True, the widget and its label will span the width of the group box. Its label will appear directly above the widget (unless the label is empty) and is left justified. @type spanWidth: bool (default False) @param borders: If true (default), this widget will have borders displayed. otherwise the won't be any outside borders around the set of radio buttons this class provides @type borders: boolean """ # Intializing label, labelColumn etc is needed before doing # PM_GroupBox.__init__. This is done so that # self.parentWidget.addPmWidget(self) done at the end of __init__ # works properly. # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a # groupbox is always appended as the 'last widget' when its # parentWidget is also a groupbox. This is due to other PM widgets #(e.g. PM_PushButton)add themselves to their parent widget in their #__init__ using self.parentWidget.addPmWidget(self). So doing the #same thing here. More general fix is needed in PM_GroupBox code # --Ninad 2007-11-14 (comment copied from PM_coordinateSpinBoxes) self.label = label self.labelColumn = labelColumn self.spanWidth = spanWidth if label: # Create this widget's QLabel. self.labelWidget = QLabel() self.labelWidget.setText(label) PM_GroupBox.__init__(self, parentWidget, title) # These are needed to properly maintain the height of the grid if # all buttons in a row are hidden via hide(). self.vBoxLayout.setMargin(0) self.vBoxLayout.setSpacing(0) self.buttonGroup = QButtonGroup() self.buttonGroup.setExclusive(True) self.parentWidget = parentWidget self.buttonList = buttonList if setAsDefault: self.setDefaultCheckedId(checkedId) self.buttonsById = {} self.buttonsByText = {} # Create radio button list from button info. for buttonInfo in buttonList: buttonId = buttonInfo[0] buttonText = buttonInfo[1] buttonToolTip = buttonInfo[2] button = QRadioButton(self) button.setText(buttonText) button.setToolTip(buttonToolTip) # Not working. button.setCheckable(True) if checkedId == buttonId: button.setChecked(True) self.buttonGroup.addButton(button, buttonId) self.vBoxLayout.addWidget(button) self.buttonsById[buttonId] = button self.buttonsByText[buttonText] = button if isinstance(self.parentWidget, PM_GroupBox): self.parentWidget.addPmWidget(self) else: #@@ Should self be added to self.parentWidget's widgetList? #don't know. Retaining old code -- Ninad 2008-06-23 self._widgetList.append(self) self._rowCount += 1 if not borders: #reset the style sheet so that there are no borders around the #radio button set this class provides. self.setStyleSheet(self._getAlternateStyleSheet())