コード例 #1
0
ファイル: keyboard.py プロジェクト: kutanari/calibre
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)
コード例 #2
0
ファイル: keyboard.py プロジェクト: siebert/calibre
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)
コード例 #3
0
    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())
コード例 #4
0
 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())