Beispiel #1
0
    def transform(self, value):
        if not value:
            return None
        style_map = {"normal": QFont.StyleNormal, "italic": QFont.StyleItalic, "oblique": QFont.StyleOblique}
        weight_map = {"normal": QFont.Normal, "bold": QFont.Bold}
        font = QFont()
        font.setStyle(QFont.StyleNormal)
        font.setWeight(QFont.Normal)

        match = self.font_regex.match(value)
        style = match.group("style")
        weight = match.group("weight")
        namedweight = match.group("namedweight")
        size = match.group("size")
        family = match.group("family")
        if style:
            font.setStyle(style_map[style])
        if namedweight:
            font.setWeight(weight_map[namedweight])
        if weight:
            # based on qcssparser.cpp:setFontWeightFromValue
            font.setWeight(min(int(weight) / 8, 99))
        if size:
            if size.lower().endswith("pt"):
                font.setPointSizeF(float(size[:-2]))
            elif size.lower().endswith("px"):
                font.setPixelSize(int(size[:-2]))
        # The Qt CSS parser handles " and ' before passing the string to
        # QFont.setFamily. We could do proper CSS-like parsing here, but since
        # hopefully nobody will ever have a font with quotes in the family (if
        # that's even possible), we take a much more naive approach.
        family = family.replace('"', "").replace("'", "")
        font.setFamily(family)
        return font
Beispiel #2
0
    def update_items(self):
        self.item = QGraphicsRectItem(0, 0, self.width,
                                      self.row_h * self.coeff_h)
        seq_width = 0
        nopen = QPen(Qt.NoPen)
        self.item.setPen(nopen)
        font = QFont(self.ftype, self.fsize)
        if self.fstyle == "italic":
            font.setStyle(QFont.StyleItalic)
        elif self.fstyle == "oblique":
            font.setStyle(QFont.StyleOblique)
        rect_cls = QGraphicsRectItem
        for i, val in enumerate(self.liste):
            width = self.col_w
            height = self.row_h * len(str(val)) + 1
            rectitem = rect_cls(0, 0, width, height, parent=self.item)
            rectitem.setX(seq_width)  # to give correct X to children item
            rectitem.setBrush(QBrush(QColor(self.bgcolor)))
            rectitem.setPen(nopen)

            # write letter if enough space in height
            if height >= self.fsize:
                text = QGraphicsSimpleTextItem(str(val), parent=rectitem)
                text.setFont(font)
                text.setBrush(QBrush(QColor(self.fgcolor)))
                # Center text according to rectitem size
                txtw = text.boundingRect().width() / 3.0
                txth = text.boundingRect().height()
                text.setRotation(self.rot)
                text.setX(txth * 1.5)
                #text.setY(0)
            seq_width += width
        self.width = seq_width
Beispiel #3
0
    class NumberBar(QWidget):
        def __init__(self, editor):
            QWidget.__init__(self, editor)

            self.editor = editor
            self.editor.blockCountChanged.connect(self.updateWidth)
            self.editor.updateRequest.connect(self.updateContents)
            self.font = QFont()
            self.numberBarColor = QColor("#e8e8e8")

        def paintEvent(self, event):

            painter = QPainter(self)
            painter.fillRect(event.rect(), self.numberBarColor)

            block = self.editor.firstVisibleBlock()

            while block.isValid():
                blockNumber = block.blockNumber()
                block_top = self.editor.blockBoundingGeometry(
                    block).translated(self.editor.contentOffset()).top()

                if blockNumber == self.editor.textCursor().blockNumber():
                    self.font.setBold(True)
                    painter.setPen(QColor("#000000"))
                else:
                    self.font.setBold(False)
                    painter.setPen(QColor("#717171"))

                paint_rect = QRect(0, block_top, self.width(),
                                   self.editor.fontMetrics().height())
                painter.drawText(paint_rect, Qt.AlignCenter,
                                 str(blockNumber + 1))

                block = block.next()

        def getWidth(self):
            count = self.editor.blockCount()
            if 0 <= count < 99999:
                width = self.fontMetrics().width('99999')
            else:
                width = self.fontMetrics().width(str(count))
            return width

        def updateWidth(self):
            width = self.getWidth()
            self.editor.setViewportMargins(width, 0, 0, 0)

        def updateContents(self, rect, dy):
            if dy:
                self.scroll(0, dy)
            else:
                self.update(0, rect.y(), self.width(), rect.height())

            if rect.contains(self.editor.viewport().rect()):
                fontSize = self.editor.currentCharFormat().font().pointSize()
                self.font.setPointSize(fontSize)
                self.font.setStyle(QFont.StyleNormal)
                self.updateWidth()
Beispiel #4
0
    def to_py(self, value):
        self._basic_py_validation(value, str)
        if not value:
            return None

        style_map = {
            'normal': QFont.StyleNormal,
            'italic': QFont.StyleItalic,
            'oblique': QFont.StyleOblique,
        }
        weight_map = {
            'normal': QFont.Normal,
            'bold': QFont.Bold,
        }
        font = QFont()
        font.setStyle(QFont.StyleNormal)
        font.setWeight(QFont.Normal)

        match = self.font_regex.match(value)
        if not match:  # pragma: no cover
            # This should never happen, as the regex always matches everything
            # as family.
            raise configexc.ValidationError(value, "must be a valid font")

        style = match.group('style')
        weight = match.group('weight')
        namedweight = match.group('namedweight')
        size = match.group('size')
        family = match.group('family')
        if style:
            font.setStyle(style_map[style])
        if namedweight:
            font.setWeight(weight_map[namedweight])
        if weight:
            # based on qcssparser.cpp:setFontWeightFromValue
            font.setWeight(min(int(weight) / 8, 99))
        if size:
            if size.lower().endswith('pt'):
                font.setPointSizeF(float(size[:-2]))
            elif size.lower().endswith('px'):
                font.setPixelSize(int(size[:-2]))
            else:
                # This should never happen as the regex only lets pt/px
                # through.
                raise ValueError("Unexpected size unit in {!r}!".format(
                    size))  # pragma: no cover

        if family == 'monospace':
            family = self.monospace_fonts
        # The Qt CSS parser handles " and ' before passing the string to
        # QFont.setFamily. We could do proper CSS-like parsing here, but since
        # hopefully nobody will ever have a font with quotes in the family (if
        # that's even possible), we take a much more naive approach.
        family = family.replace('"', '').replace("'", '')
        font.setFamily(family)

        return font
Beispiel #5
0
 def __set_file_text(self, data):
     """
     Displayed in the chat of the user who sends a file
     """
     tab = self.set_data_to_correct_tab(data['type'])
     font = QFont()
     font.setStyle(QFont.StyleItalic)
     item = QListWidgetItem(tab.children()[0])
     item.setFont(font)
     item.setText("%s: Send file" % self.members[data['username']].username)
Beispiel #6
0
 def pushBtnFont(self):
     font = QFont()
     font.setFamily("宋体")
     font.setPixelSize(30)
     font.setBold(True)
     font.setItalic(True)
     font.setPointSize(20)
     font.setStyle(QFont.StyleItalic)
     font.setWeight(QFont.Light)
     return font
Beispiel #7
0
    def to_py(self, value):
        self._basic_py_validation(value, str)
        if not value:
            return None

        style_map = {
            'normal': QFont.StyleNormal,
            'italic': QFont.StyleItalic,
            'oblique': QFont.StyleOblique,
        }
        weight_map = {
            'normal': QFont.Normal,
            'bold': QFont.Bold,
        }
        font = QFont()
        font.setStyle(QFont.StyleNormal)
        font.setWeight(QFont.Normal)

        match = self.font_regex.match(value)
        if not match:  # pragma: no cover
            # This should never happen, as the regex always matches everything
            # as family.
            raise configexc.ValidationError(value, "must be a valid font")

        style = match.group('style')
        weight = match.group('weight')
        namedweight = match.group('namedweight')
        size = match.group('size')
        family = match.group('family')
        if style:
            font.setStyle(style_map[style])
        if namedweight:
            font.setWeight(weight_map[namedweight])
        if weight:
            # based on qcssparser.cpp:setFontWeightFromValue
            font.setWeight(min(int(weight) / 8, 99))
        if size:
            if size.lower().endswith('pt'):
                font.setPointSizeF(float(size[:-2]))
            elif size.lower().endswith('px'):
                font.setPixelSize(int(size[:-2]))
            else:
                # This should never happen as the regex only lets pt/px
                # through.
                raise ValueError("Unexpected size unit in {!r}!".format(
                    size))  # pragma: no cover
        # The Qt CSS parser handles " and ' before passing the string to
        # QFont.setFamily. We could do proper CSS-like parsing here, but since
        # hopefully nobody will ever have a font with quotes in the family (if
        # that's even possible), we take a much more naive approach.
        family = family.replace('"', '').replace("'", '')
        if family == 'monospace':
            family = self.monospace_fonts
        font.setFamily(family)
        return font
Beispiel #8
0
 def send_file(self, main_window_instance):
     index_first_tab = main_window_instance.tab_widget.currentIndex()
     if index_first_tab != 0:
         file_text = QFileDialog().getOpenFileName()
         current_tab = main_window_instance.tab_widget.currentWidget()
         current_widget = current_tab.children()[0]
         font = QFont()
         font.setStyle(QFont.StyleItalic)
         item = QListWidgetItem(current_widget)
         item.setFont(font)
         item.setText("%s: %s" % (self.username, "Sending File..."))
         self.client.send(file_text, current_tab, is_file=True)
Beispiel #9
0
 def load_font(self):
     """Apply a QFont object if present."""
     if self.settings.font is None:
         return
     try:
         font = QFont(self.settings.font['family'],
                      self.settings.font['point_size'],
                      self.settings.font['weight'],
                      self.settings.font['italic'])
         font.setStyle(self.settings.font['style'])
         font.setPointSize(self.settings.font['point_size'])
         font.setStrikeOut(self.settings.font['strikeout'])
         font.setUnderline(self.settings.font['underline'])
         self.apply_font(font)
     except Exception:  # Invalid font
         pass
Beispiel #10
0
 def __init__(self, title, parent, icon=None):
     QMenu.__init__(self, title, parent)
     if icon is None:
         title = '\u2022 ' + title
         self._title = self.addAction(title)
     else:
         if isinstance(icon, str):
             ##icon = QIcon(png(icon))
             icon = QIcon(png_pth(icon))
         self._title = self.addAction(icon, title)
     self._title.setEnabled(False)
     self._title.setIconVisibleInMenu(True)
     font = QFont()
     font.setBold(True)
     font.setStyle(QFont.StyleItalic)
     self._title.setFont(font)
     self.addSeparator()
Beispiel #11
0
    def transform(self, value):
        if not value:
            return None
        style_map = {
            'normal': QFont.StyleNormal,
            'italic': QFont.StyleItalic,
            'oblique': QFont.StyleOblique,
        }
        weight_map = {
            'normal': QFont.Normal,
            'bold': QFont.Bold,
        }
        font = QFont()
        font.setStyle(QFont.StyleNormal)
        font.setWeight(QFont.Normal)

        match = self.font_regex.match(value)
        style = match.group('style')
        weight = match.group('weight')
        namedweight = match.group('namedweight')
        size = match.group('size')
        family = match.group('family')
        if style:
            font.setStyle(style_map[style])
        if namedweight:
            font.setWeight(weight_map[namedweight])
        if weight:
            # based on qcssparser.cpp:setFontWeightFromValue
            font.setWeight(min(int(weight) / 8, 99))
        if size:
            if size.lower().endswith('pt'):
                font.setPointSizeF(float(size[:-2]))
            elif size.lower().endswith('px'):
                font.setPixelSize(int(size[:-2]))
        # The Qt CSS parser handles " and ' before passing the string to
        # QFont.setFamily. We could do proper CSS-like parsing here, but since
        # hopefully nobody will ever have a font with quotes in the family (if
        # that's even possible), we take a much more naive approach.
        family = family.replace('"', '').replace("'", '')
        font.setFamily(family)
        return font
Beispiel #12
0
    class NumberBar(QWidget):
        '''class that deifnes textEditor numberBar'''

        def __init__(self, editor):
            QWidget.__init__(self, editor)
            
            self.editor = editor
            self.editor.blockCountChanged.connect(self.updateWidth)
            self.editor.updateRequest.connect(self.updateContents)
            self.font = QFont()
            self.numberBarColor = QColor("#e8e8e8")
                     
        def paintEvent(self, event):
            
            painter = QPainter(self)
            painter.fillRect(event.rect(), self.numberBarColor)
             
            block = self.editor.firstVisibleBlock()
 
            # Iterate over all visible text blocks in the document.
            while block.isValid():
                blockNumber = block.blockNumber()
                block_top = self.editor.blockBoundingGeometry(block).translated(self.editor.contentOffset()).top()
 
                # Check if the position of the block is out side of the visible area.
                if not block.isVisible() or block_top >= event.rect().bottom():
                    break
 
                # We want the line number for the selected line to be bold.
                if blockNumber == self.editor.textCursor().blockNumber():
                    self.font.setBold(True)
                    painter.setPen(QColor("#000000"))
                else:
                    self.font.setBold(False)
                    painter.setPen(QColor("#717171"))
                painter.setFont(self.font)
                
                # Draw the line number right justified at the position of the line.
                paint_rect = QRect(0, block_top, self.width(), self.editor.fontMetrics().height())
                painter.drawText(paint_rect, Qt.AlignRight, str(blockNumber+1))
 
                block = block.next()
 
            painter.end()
            
            QWidget.paintEvent(self, event)
 
        def getWidth(self):
            count = self.editor.blockCount()
            width = self.fontMetrics().width(str(count)) + 5
            return width      
        
        def updateWidth(self):
            width = self.getWidth() + 5
            if self.width() != width:
                self.setFixedWidth(width)
                self.editor.setViewportMargins(width, 0, 0, 0)
 
        def updateContents(self, rect, scroll):
            if scroll:
                self.scroll(0, scroll)
            else:
                self.update(0, rect.y(), self.width(), rect.height())
            
            if rect.contains(self.editor.viewport().rect()):   
                fontSize = self.editor.currentCharFormat().font().pointSize()
                self.font.setPointSize(fontSize)
                self.font.setStyle(QFont.StyleNormal)
                self.updateWidth()
Beispiel #13
0
    def __init__(self, parent, path=""):
        #super().__init__()
        super(TextEdit, self).__init__(parent)

        self.parent = parent
        self.path = path

        font = QFont("Monospace", 8)  #QFont()
        #font.setFamily("Monospace")
        font.setStyleHint(QFont.Monospace)
        font.setStyle(QFont.StyleNormal)
        font.setStyleStrategy(QFont.PreferDefault)
        font.setWeight(QFont.ExtraLight)
        font.setCapitalization(QFont.MixedCase)
        font.setHintingPreference(QFont.PreferDefaultHinting)
        font.setLetterSpacing(QFont.PercentageSpacing, 100.0)
        font.setStretch(QFont.AnyStretch)

        font.setBold(False)
        font.setFixedPitch(True)
        font.setItalic(False)
        font.setKerning(True)
        font.setOverline(False)  # sobrelinea
        #font.setPixelSize(8) #font.setPointSize(8) font.setPointSizeF(8)
        font.setStrikeOut(False)  # tachado
        #font.setStyleName()
        font.setUnderline(False)
        #font.setWordSpacing(1)
        print(font.toString())

        charFormat = QTextCharFormat()
        charFormat.setFont(font)

        #self.setTabStopWidth(4)
        self.setCursorWidth(5)
        self.setCurrentCharFormat(charFormat)
        #print(self.document().defaultTextOption())

        #FIXME: Usaremos qss
        pal = QPalette()
        bgc = QColor(39, 40, 34)
        pal.setColor(QPalette.Base, bgc)
        textc = QColor(255, 255, 255)
        pal.setColor(QPalette.Text, textc)
        self.setPalette(pal)

        self.setLineWrapMode(QPlainTextEdit.NoWrap)

        #self.setTextBackgroundColor(QColor(0, 255, 255))
        #self.setTextColor(QColor(0, 255, 255))
        #self.setFontWeight(QFont.Normal)

        #cursor = self.textCursor()
        #cursor.movePosition(QTextCursor.End)
        #self.setDocumentTitle("Coso")

        #self.syntaxHighlighter = PythonHighlighter(self.document())

        # Señales
        #self.blockCountChanged.connect(self.__newBlock)
        #self.cursorPositionChanged.connect()
        #self.selectionChanged.connect(self.__changedSelection)
        #self.textChanged.connect(self.__changedText)
        #self.updateRequest.connect((const QRect &rect, int dy)
        #self.modificationChanged.connect(self.__chanedModification)

        #self.copyAvailable.connect(self.__copyAvailable)
        #self.undoAvailable.connect(self.__undoAvailable)
        #self.redoAvailable.connect(self.__redoAvailable)

        if os.path.exists(self.path):
            file = open(self.path, 'r')
            data = file.read()
            texto = self.__limpiar_codigo(data)
            self.setPlainText(texto)
            self.document().setModified(data != texto)
            if data != texto:
                print("El texto fue corregido al abrir el archivo.")
        else:
            self.setPlainText(
                "#!/usr/bin/python3\n# -*- coding: utf-8 -*-\n\n")
            self.document().setModified(True)

        self.setFocus()
Beispiel #14
0
class Piano(QWidget):
    def __init__(self):
        super().__init__()
        self.volume = 63
        self.octave = 3
        self.control = 0

        self.octave_changed_time = 0

        self.control_lbl_style = 'QLable{text-align: center; color: #8B795E; font-style: Century Gothic; font-size: 16;}'
        self.option_lbl_font = QFont()
        self.option_lbl_font.setFamily('Century Gothic')
        self.option_lbl_font.setWeight(QFont.Bold)
        self.option_lbl_font.setStyle(QFont.StyleItalic)
        self.option_lbl_font.setPixelSize(16)

        self.combo_style = 'QComboBox{background-color: #FFF5EE; color: #8B5A2B; text-align: center;}'
        self.spin_style = 'QSpinBox{background-color: #FFF5EE; color: #8B5A2B;}'
        self.input_font = QFont()
        self.input_font.setFamily('Century Gothic')
        self.input_font.setWeight(QFont.DemiBold)
        self.input_font.setStyle(QFont.StyleNormal)
        self.input_font.setPixelSize(14)

        self.instr_type_list = get_instrument_types()
        self.instr_list = get_instrument_list()
        self.instr_type_index = 0
        self.instr_index = 0

        self.is_record_mode = False
        self.music_segment = None

        self.show_window_on = False

        self.metre = '1/4'
        self.metre_numerator = 1
        self.metre_denominator = 4
        self.metre_options = ['1/4', '2/4', '3/4', '4/4', '3/8', '6/8']
        self.metre_effects = {
            '1/4': (1, 4),
            '2/4': (2, 4),
            '3/4': (3, 4),
            '4/4': (4, 4),
            '3/8': (3, 8),
            '6/8': (6, 8)
        }

        self.length_per_note = 1 / 4
        self.length_per_note_options = [
            '1/16', '1/8', '1/4', '3/4', '1/2', '1', '3/2', '2', '3', '4'
        ]
        self.length_per_note_effects = [
            1 / 16, 1 / 8, 1 / 4, 3 / 4, 1 / 2, 1, 3 / 2, 2, 3, 4
        ]
        self.length_per_note_index = 2

        self.beats_per_minute = 120

        # self.root_notes_list = [distance for distance in range(12)]

        self.root_note_names = [
            note_number_to_name(num, 'f', False)
            for num in [note for note in range(12)]
        ]
        self.root_note_index = 0
        self.root_note_name = self.root_note_names[self.root_note_index]

        self.mode_type_list = get_mode_types()
        self.mode_list = get_mode_name_list()
        self.mode_pattern_list = get_mode_pattern_list()
        self.mode_type = 'Heptatonic'
        self.mode_name = 'Ionian'
        self.mode_type_index = 0

        self.mode_display = False

        self.white_shortcuts = [[
            Qt.Key_Z, Qt.Key_X, Qt.Key_C, Qt.Key_V, Qt.Key_B, Qt.Key_N,
            Qt.Key_M
        ],
                                [
                                    Qt.Key_Q, Qt.Key_W, Qt.Key_E, Qt.Key_R,
                                    Qt.Key_T, Qt.Key_Y, Qt.Key_U, Qt.Key_I
                                ]]
        self.black_shortcuts = [[
            Qt.Key_S, Qt.Key_D, Qt.Key_G, Qt.Key_H, Qt.Key_J
        ], [Qt.Key_2, Qt.Key_3, Qt.Key_5, Qt.Key_6, Qt.Key_7]]

        pygame.midi.init()

        self.player = pygame.midi.Output(0)
        self.player.set_instrument(self.instr_index)

        self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                    (self.mode_type, self.mode_name),
                                    self.root_note_name, self.mode_display)

        self.initUI()

    def initUI(self):
        self.record_start_btn = RecordBtn(
            resource_path('icon/clipboard_start.png'), 'Start Recording (F1)',
            Qt.Key_F1)
        self.record_start_btn.clicked.connect(self.recordStart)

        self.record_draw_btn = RecordBtn(
            resource_path('icon/clipboard_see.png'), 'Draw Notes Plot (F2)',
            Qt.Key_F2)
        self.record_draw_btn.clicked.connect(self.recordDraw)

        self.record_play_btn = RecordBtn(
            resource_path('icon/clipboard_play.png'),
            'Play Recorded Segment (F3)', Qt.Key_F3)
        self.record_play_btn.clicked.connect(self.recordPlay)

        self.record_return_btn = RecordBtn(
            resource_path('icon/clipboard_return.png'),
            'Delete Last Note (F4)', Qt.Key_F4)
        self.record_return_btn.clicked.connect(self.recordReturn)

        self.record_rest_btn = RecordBtn(
            resource_path('icon/clipboard_rest.png'), 'Insert A Rest (F5)',
            Qt.Key_F5)
        self.record_rest_btn.clicked.connect(self.recordRest)

        self.record_finish_btn = RecordBtn(
            resource_path('icon/clipboard_finish.png'),
            'Finish Recording (F6)', Qt.Key_F6)
        self.record_finish_btn.clicked.connect(self.recordFinish)

        self.record_stop_btn = RecordBtn(
            resource_path('icon/clipboard_stop.png'), 'Stop Recording (F7)',
            Qt.Key_F7)
        self.record_stop_btn.clicked.connect(self.recordStop)

        self.record_btn_box = QHBoxLayout()
        self.record_btn_box.addWidget(self.record_start_btn)
        self.record_btn_box.addWidget(self.record_draw_btn)
        self.record_btn_box.addWidget(self.record_play_btn)
        self.record_btn_box.addWidget(self.record_return_btn)
        self.record_btn_box.addWidget(self.record_rest_btn)
        self.record_btn_box.addWidget(self.record_finish_btn)
        self.record_btn_box.addWidget(self.record_stop_btn)
        self.record_btn_box.setContentsMargins(5, 5, 5, 10)

        self.LPN_lbl = QLabel('LPN:')
        self.LPN_lbl.setAlignment(Qt.AlignCenter)
        self.LPN_lbl.setFont(self.option_lbl_font)
        self.LPN_ctrl = QComboBox()
        self.LPN_ctrl.addItems(self.length_per_note_options)
        self.LPN_ctrl.setCurrentIndex(self.length_per_note_index)
        self.LPN_ctrl.setFont(self.input_font)
        self.LPN_ctrl.setStyleSheet(self.combo_style)
        self.LPN_ctrl.currentIndexChanged.connect(self.LPNChanged)
        self.LPN_box = QHBoxLayout()
        self.LPN_box.addWidget(self.LPN_lbl)
        self.LPN_box.addWidget(self.LPN_ctrl)

        self.metre_lbl = QLabel('Metre:')
        self.metre_lbl.setAlignment(Qt.AlignCenter)
        self.metre_lbl.setFont(self.option_lbl_font)
        self.metre_ctrl = QComboBox()
        self.metre_ctrl.addItems(self.metre_options)
        self.metre_ctrl.setFont(self.input_font)
        self.metre_ctrl.setStyleSheet(self.combo_style)
        self.metre_ctrl.currentIndexChanged.connect(self.metreChanged)
        self.metre_box = QHBoxLayout()
        self.metre_box.addWidget(self.metre_lbl)
        self.metre_box.addWidget(self.metre_ctrl)

        self.BPM_lbl = QLabel('BPM:')
        self.BPM_lbl.setAlignment(Qt.AlignCenter)
        self.BPM_lbl.setFont(self.option_lbl_font)
        self.BPM_ctrl = QSpinBox()
        self.BPM_ctrl.setRange(40, 208)
        self.BPM_ctrl.setValue(self.beats_per_minute)
        self.BPM_ctrl.setAlignment(Qt.AlignCenter)
        self.BPM_ctrl.setStyleSheet(self.spin_style)
        self.BPM_ctrl.valueChanged.connect(self.BPMChanged)
        self.BPM_ctrl.setFont(self.input_font)
        self.BPM_ctrl.setFocusPolicy(Qt.NoFocus)
        self.BPM_box = QHBoxLayout()
        self.BPM_box.addWidget(self.BPM_lbl)
        self.BPM_box.addWidget(self.BPM_ctrl)

        self.root_note_lbl = QLabel('Root Note:')
        self.root_note_lbl.setAlignment(Qt.AlignCenter)
        self.root_note_lbl.setFont(self.option_lbl_font)
        self.root_note_ctrl = QComboBox()
        self.root_note_ctrl.addItems(self.root_note_names)
        self.root_note_ctrl.setFont(self.input_font)
        self.root_note_ctrl.setStyleSheet(self.combo_style)
        self.root_note_ctrl.currentIndexChanged.connect(self.rootNoteChanged)
        self.root_note_box = QHBoxLayout()
        self.root_note_box.addWidget(self.root_note_lbl)
        self.root_note_box.addWidget(self.root_note_ctrl)

        self.mode_box = QHBoxLayout()
        self.mode_lbl = QLabel('Mode:')
        self.mode_lbl.setAlignment(Qt.AlignCenter)
        self.mode_lbl.setFont(self.option_lbl_font)
        self.mode_type_combo = QComboBox()
        self.mode_type_combo.setStyleSheet(self.combo_style)
        self.mode_type_combo.setFont(self.input_font)
        self.mode_type_combo.addItems(self.mode_type_list)
        self.mode_type_combo.setFocusPolicy(Qt.NoFocus)
        self.mode_type_combo.currentIndexChanged.connect(self.modeTypeChanged)
        self.mode_combo = QComboBox()
        self.mode_combo.setStyleSheet(self.combo_style)
        self.mode_combo.setFont(self.input_font)
        self.mode_combo.addItems(self.mode_list[self.mode_type_index])
        self.mode_combo.setFocusPolicy(Qt.NoFocus)
        self.mode_combo.currentIndexChanged.connect(self.modeChanged)
        self.mode_box.addWidget(self.mode_lbl)
        self.mode_box.addWidget(self.mode_type_combo)
        self.mode_box.addWidget(self.mode_combo)

        self.record_option_box = QVBoxLayout()
        self.record_option_box_first = QHBoxLayout()
        self.record_option_box_second = QHBoxLayout()
        self.record_option_box_first.addLayout(self.LPN_box)
        self.record_option_box_first.addLayout(self.metre_box)
        self.record_option_box_first.addLayout(self.BPM_box)
        self.record_option_box_second.addLayout(self.root_note_box)
        self.record_option_box_second.addLayout(self.mode_box)
        self.record_option_box.addLayout(self.record_option_box_first)
        self.record_option_box.addLayout(self.record_option_box_second)
        self.record_option_box.setSpacing(20)
        # self.record_option_box.setSpacing(10)

        self.record_box = QVBoxLayout()
        self.record_box.addLayout(self.record_btn_box)
        self.record_box.addLayout(self.record_option_box)
        self.record_box.setStretch(0, 2)
        self.record_box.setStretch(1, 3)

        self.volume_box = QHBoxLayout()
        self.volume_lbl = QLabel('Volume:')
        self.volume_lbl.setAlignment(Qt.AlignCenter)
        self.volume_lbl.setFont(self.option_lbl_font)
        self.volume_ctrl = QSlider(Qt.Horizontal)
        self.volume_ctrl.setTickPosition(QSlider.TicksBothSides)
        self.volume_ctrl.setSingleStep(8)
        self.volume_ctrl.setTickInterval(16)
        self.volume_ctrl.setFixedWidth(300)
        self.volume_ctrl.setFixedHeight(15)
        self.volume_ctrl.setRange(0, 127)
        self.volume_ctrl.setStyleSheet(
            'QSlider:groove{ border-radius: 6px;}'
            'QSlider:handle{width: 15px; background-color: #8B7765; border-radius: 6px; border: 1px solid #8B4513;}'
            'QSlider:add-page{background-color: #EECFA1; border-radius: 6px;}'
            'QSlider:sub-page{background-color: #FFA07A; border-radius: 6px;}')

        self.volume_ctrl.setValue(self.volume)
        self.volume_ctrl.setFocusPolicy(Qt.NoFocus)
        self.volume_ctrl.sliderReleased.connect(self.volumeChanged)
        self.mode_display_check = QCheckBox('Mode Display')
        self.mode_display_check.setFont(self.option_lbl_font)
        # self.mode_display_check.setStyleSheet()
        self.mode_display_check.stateChanged.connect(self.modeDisplayChanged)
        self.volume_box.addWidget(self.volume_lbl)
        self.volume_box.addWidget(self.volume_ctrl)
        self.volume_box.addWidget(self.mode_display_check)
        self.volume_box.setAlignment(Qt.AlignLeft)
        self.volume_box.setStretch(0, 1)
        self.volume_box.setStretch(1, 4)
        self.volume_box.setStretch(2, 1)

        self.octave_box = QHBoxLayout()
        self.octave_lbl = QLabel('Octave:')
        self.octave_lbl.setAlignment(Qt.AlignCenter)
        self.octave_lbl.setFont(self.option_lbl_font)
        self.octave_ctrl = QSpinBox()
        self.octave_ctrl.setStyleSheet(self.spin_style)
        self.octave_ctrl.setAlignment(Qt.AlignCenter)
        self.octave_ctrl.setFont(self.input_font)
        self.octave_ctrl.setRange(0, 8)
        self.octave_ctrl.setSingleStep(1)
        self.octave_ctrl.setValue(self.octave)
        self.octave_ctrl.setWrapping(True)
        self.octave_ctrl.setFocusPolicy(Qt.NoFocus)
        self.octave_ctrl.valueChanged.connect(self.octaveChanged)
        self.octave_box.addWidget(self.octave_lbl)
        self.octave_box.addWidget(self.octave_ctrl)
        octave_up = QShortcut(QKeySequence(Qt.Key_PageUp), self)
        octave_up.activated.connect(self.octaveIncrease)
        octave_down = QShortcut(QKeySequence(Qt.Key_PageDown), self)
        octave_down.activated.connect(self.octaveDecrease)

        self.instr_box = QHBoxLayout()
        self.instr_lbl = QLabel('Instrument:')
        self.instr_lbl.setAlignment(Qt.AlignCenter)
        self.instr_lbl.setFont(self.option_lbl_font)
        self.instr_type_combo = QComboBox()
        self.instr_type_combo.setStyleSheet(self.combo_style)
        self.instr_type_combo.setFont(self.input_font)
        self.instr_type_combo.addItems(self.instr_type_list)
        self.instr_type_combo.setFocusPolicy(Qt.NoFocus)
        self.instr_type_combo.currentIndexChanged.connect(
            self.instrTypeChanged)
        self.instr_combo = QComboBox()
        self.instr_combo.setStyleSheet(self.combo_style)
        self.instr_combo.setFont(self.input_font)
        self.instr_combo.addItems(self.instr_list[self.instr_type_index])
        self.instr_combo.setFocusPolicy(Qt.NoFocus)
        self.instr_combo.currentIndexChanged.connect(self.instrChanged)
        self.instr_box.addWidget(self.instr_lbl)
        self.instr_box.addWidget(self.instr_type_combo)
        self.instr_box.addWidget(self.instr_combo)

        self.pianoroll_option_box = QVBoxLayout()
        self.pianoroll_option_box.addLayout(self.volume_box)
        self.pianoroll_option_box.addLayout(self.octave_box)
        self.pianoroll_option_box.addLayout(self.instr_box)
        # self.pianoroll_option_box.addLayout(self.mode_display_box)
        self.pianoroll_option_box.setStretch(0, 5)
        self.pianoroll_option_box.setStretch(1, 5)
        self.pianoroll_option_box.setStretch(2, 5)

        self.option_box = QHBoxLayout()
        self.option_box.addLayout(self.record_box)
        self.option_box.addLayout(self.pianoroll_option_box)
        self.option_box.setStretch(0, 9)
        self.option_box.setStretch(1, 6)

        self.optionField = QWidget()
        self.optionField.setObjectName('OptionField')
        self.optionField.setLayout(self.option_box)
        self.optionField.setStyleSheet(
            'QWidget#OptionField{background-color: #CDC0B0; border: 5px ridge #8B795E;}'
        )

        self.pianorollBox = QHBoxLayout()
        self.pianorollWindow = QMainWindow()
        self.pianorollWindow.setObjectName('PianoRollWindow')
        self.pianorollWindow.setStyleSheet(
            'QMainWindow#PianoRollWindow{background-color: #FFF5EE;}')
        self.pianorollBox.addWidget(self.pianorollWindow)
        self.pianorollWindow.setCentralWidget(self.piano_roll)

        self.wholeLayout = QVBoxLayout()
        self.wholeLayout.addWidget(self.optionField)
        self.wholeLayout.addLayout(self.pianorollBox)

        self.setLayout(self.wholeLayout)

    def recordStart(self):

        self.is_record_mode = True

        choice_box = QMessageBox()
        choice_box.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
        choice_box.setIcon(QMessageBox.Question)
        choice_box.setText('Continue from an existing file?')
        choice_box.setWindowTitle('Continue?')
        choice_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        # save_box.buttonClicked.connect(self.saveBtnResponse)
        choice_box.show()

        retval = choice_box.exec_()

        if retval == QMessageBox.Yes:
            file_name, _ = QFileDialog.getOpenFileName(
                self, r'Please choose a file', 'd:', r'JSON Files(*.json)')
            if file_name == '':
                new_choice_box = QMessageBox()
                new_choice_box.setWindowIcon(
                    QIcon(resource_path('icon/gramophone.png')))
                new_choice_box.setIcon(QMessageBox.Warning)
                new_choice_box.setText(
                    'Not a valid file, continue from an existing file?')
                new_choice_box.setWindowTitle('Continue?')
                new_choice_box.setStandardButtons(QMessageBox.Yes
                                                  | QMessageBox.No)
                new_choice_box.show()
                retval2 = new_choice_box.exec_()

                if retval2 == QMessageBox.Yes:
                    self.music_segment = MusicSegment(
                        self.metre, self.beats_per_minute, self.root_note_name,
                        (self.mode_type, self.mode_name))
                    self.music_segment.set_length_per_note(
                        self.length_per_note)
                    self.music_segment.set_volume(self.volume)

                    self.piano_roll.start_recording(self.music_segment)
                    self.record_start_btn.setStyleSheet(
                        'QPushButton{background: #8B8682; border: 3px inset #8B8378; border-radius: 15px;}'
                    )

                else:
                    return
            else:
                self.music_segment = MusicSegment.load(file_name)
                self.piano_roll.start_recording(self.music_segment)
                self.record_start_btn.setStyleSheet(
                    'QPushButton{background: #8B8682; border: 3px inset #8B8378; border-radius: 15px;}'
                )

        else:
            self.music_segment = MusicSegment(self.metre,
                                              self.beats_per_minute,
                                              self.root_note_name,
                                              (self.mode_type, self.mode_name))
            self.music_segment.set_length_per_note(self.length_per_note)
            self.music_segment.set_volume(self.volume)

            self.piano_roll.start_recording(self.music_segment)
            self.record_start_btn.setStyleSheet(
                'QPushButton{background: #8B8682; border: 3px inset #8B8378; border-radius: 15px;}'
            )

    def recordDraw(self):
        if self.is_record_mode == True and self.music_segment != None:
            if self.music_segment.window_on == False:
                self.music_segment.segment_window = SegmentWindow(
                    self.music_segment)
                self.music_segment.segment_window.show()
                self.music_segment.segment_window.move(1510, 125)
                self.setFocus()
                self.music_segment.window_on = True
        else:
            msg = QMessageBox()
            msg.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
            msg.setIcon(QMessageBox.Information)
            msg.setText('Please first start record mode')
            msg.setWindowTitle('Not in Record Mode')
            msg.setStandardButtons(QMessageBox.Ok)
            msg.show()
            retval = msg.exec_()

    def recordPlay(self):
        if self.is_record_mode == True and self.music_segment != None:
            self.music_segment.play_music(self.piano_roll.player)
        else:
            msg = QMessageBox()
            msg.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
            msg.setIcon(QMessageBox.Information)
            msg.setText('Please first start record mode')
            msg.setWindowTitle('Not in Record Mode')
            msg.setStandardButtons(QMessageBox.Ok)
            msg.show()
            retval = msg.exec_()

    def recordReturn(self):
        if self.is_record_mode == True and self.music_segment != None:
            if self.music_segment.is_empty():
                msg = QMessageBox()
                msg.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
                msg.setIcon(QMessageBox.Information)
                msg.setText('No note to delete.')
                msg.setWindowTitle('Empty Segment')
                msg.setStandardButtons(QMessageBox.Ok)
                msg.show()
                retval = msg.exec_()
            else:
                self.music_segment.delete_last_msg()
                self.music_segment.replot()
        else:
            msg = QMessageBox()
            msg.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
            msg.setIcon(QMessageBox.Information)
            msg.setText('Please first start record mode')
            msg.setWindowTitle('Not in Record Mode')
            msg.setStandardButtons(QMessageBox.Ok)
            msg.show()
            retval = msg.exec_()

    def recordRest(self):
        if not self.is_record_mode:
            msg = QMessageBox()
            msg.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
            msg.setIcon(QMessageBox.Information)
            msg.setText('Please first start record mode')
            msg.setWindowTitle('Not in Record Mode')
            msg.setStandardButtons(QMessageBox.Ok)
            msg.show()
            retval = msg.exec_()

        else:
            self.music_segment.add_rest(self.music_segment.length_per_note)
            if self.music_segment.window_on == True:
                self.music_segment.replot()

    def recordFinish(self):
        if self.is_record_mode == True and self.music_segment != None:
            self.is_record_mode = False
            self.piano_roll.end_recording()
            self.record_start_btn.setStyleSheet(
                'QPushButton{background: #FFEFDB; border: 3px outset #8B8378; border-radius: 15px;}'
                'QPushButton:hover{background: #CDC9C9; border: 3px outset #8B8378; border-radius: 15px;}'
                'QPushButton:pressed{background: #8B8682; border: 3px inset #8B8378; border-radius: 15px;}'
            )
            save_box = QMessageBox()
            save_box.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
            save_box.setIcon(QMessageBox.Question)
            save_box.setText('Save Music Segment?')
            save_box.setWindowTitle('Save Music Segment')
            save_box.setStandardButtons(QMessageBox.Save | QMessageBox.No)
            # save_box.buttonClicked.connect(self.saveBtnResponse)
            save_box.show()

            retval = save_box.exec_()
            if retval == QMessageBox.Save:
                print('save')
                file_name, _ = QFileDialog.getSaveFileName(
                    self, r'Please choose where to save', 'd:',
                    r'JSON Files(*.json)')
                if file_name != '':
                    self.music_segment.save(file_name)
            elif retval == QMessageBox.No:
                print('no')
            else:
                pass
        else:
            msg = QMessageBox()
            msg.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
            msg.setIcon(QMessageBox.Information)
            msg.setText('Please first start record mode')
            msg.setWindowTitle('Not in Record Mode')
            msg.setStandardButtons(QMessageBox.Ok)
            msg.show()
            retval = msg.exec_()

    def recordStop(self):
        if not self.is_record_mode:
            msg = QMessageBox()
            msg.setWindowIcon(QIcon(resource_path('icon/gramophone.png')))
            msg.setIcon(QMessageBox.Information)
            msg.setText('Please first start record mode')
            msg.setWindowTitle('Not in Record Mode')
            msg.setStandardButtons(QMessageBox.Ok)
            msg.show()
            retval = msg.exec_()
        else:
            self.is_record_mode = False
            self.piano_roll.end_recording()
            self.record_start_btn.setStyleSheet(
                'QPushButton{background: #FFEFDB; border: 3px outset #8B8378; border-radius: 15px;}'
                'QPushButton:hover{background: #CDC9C9; border: 3px outset #8B8378; border-radius: 15px;}'
                'QPushButton:pressed{background: #8B8682; border: 3px inset #8B8378; border-radius: 15px;}'
            )

    def LPNChanged(self):
        self.length_per_note = self.length_per_note_effects[
            self.LPN_ctrl.currentIndex()]
        if self.is_record_mode:
            self.music_segment.set_length_per_note(self.length_per_note)

    def metreChanged(self):
        self.metre = self.metre_ctrl.currentText()
        self.metre_numerator = self.metre_effects[self.metre][0]
        self.metre_denominator = self.metre_effects[self.metre][1]

        if self.is_record_mode:
            self.music_segment.metre = self.metre
            self.music_segment.metre_numerator = self.metre_numerator
            self.music_segment.metre_denominator = self.metre_denominator

    def BPMChanged(self):
        self.beats_per_minute = self.BPM_ctrl.value()
        if self.is_record_mode:
            self.music_segment.bpm = self.beats_per_minute
            self.music_segment.time_per_unit = (60 / self.music_segment.bpm)

    def rootNoteChanged(self):
        self.root_note_index = self.root_note_ctrl.currentIndex()
        self.root_note_name = self.root_note_names[self.root_note_index]
        self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                    (self.mode_type, self.mode_name),
                                    self.root_note_name, self.mode_display)
        self.pianorollWindow.setCentralWidget(self.piano_roll)

        if self.is_record_mode:
            self.music_segment.root_note = self.root_note

    def modeTypeChanged(self):
        self.mode_type_index = self.mode_type_combo.currentIndex()
        self.mode_type = self.mode_type_list[self.mode_type_index]
        # self.mode_combo.disconnect()
        self.mode_combo.clear()
        self.mode_combo.addItems(self.mode_list[self.mode_type_index])
        self.mode_combo.update()

        self.mode_name = self.mode_combo.currentText()

        if self.is_record_mode:
            self.music_segment.mode = (self.mode_type, self.mode_name)

        self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                    (self.mode_type, self.mode_name),
                                    self.root_note_name, self.mode_display)
        self.pianorollWindow.setCentralWidget(self.piano_roll)

    def modeChanged(self):
        self.mode_name = self.mode_list[self.mode_type_index][
            self.mode_combo.currentIndex()]
        if self.is_record_mode:
            self.music_segment.mode = (self.mode_type, self.mode_name)
            self.piano_roll.start_recording(self.music_segment)
        self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                    (self.mode_type, self.mode_name),
                                    self.root_note_name, self.mode_display)
        self.pianorollWindow.setCentralWidget(self.piano_roll)

    def volumeChanged(self):
        self.volume = self.volume_ctrl.value()
        self.piano_roll.change_volume(self.volume)
        self.pianorollWindow.setCentralWidget(self.piano_roll)
        if self.is_record_mode:
            self.music_segment.set_volume(self.volume)

    def octaveChanged(self):
        self.octave = self.octave_ctrl.value()

        self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                    (self.mode_type, self.mode_name),
                                    self.root_note_name, self.mode_display)
        self.pianorollWindow.setCentralWidget(self.piano_roll)

        if self.is_record_mode:
            self.piano_roll.start_recording(self.music_segment)

    def instrTypeChanged(self):
        self.instr_type_index = self.instr_type_combo.currentIndex()
        # self.instr_combo.disconnect()
        self.instr_combo.clear()
        self.instr_combo.addItems(self.instr_list[self.instr_type_index])
        self.instr_index = sum(get_instrument_margin()[:self.instr_type_index]
                               ) + self.instr_combo.currentIndex()
        self.instr_combo.update()
        self.player.set_instrument(self.instr_index)

    def instrChanged(self):
        self.instr_index = sum(get_instrument_margin()[:self.instr_type_index]
                               ) + self.instr_combo.currentIndex()
        self.player.set_instrument(self.instr_index)

    def modeDisplayChanged(self):
        self.mode_display = self.mode_display_check.isChecked()
        self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                    (self.mode_type, self.mode_name),
                                    self.root_note_name, self.mode_display)
        self.pianorollWindow.setCentralWidget(self.piano_roll)

    def octaveIncrease(self):
        if self.octave < 8:
            self.octave = self.octave + 1
            self.octave_ctrl.setValue(self.octave)
            self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                        (self.mode_type, self.mode_name),
                                        self.root_note_name, self.mode_display)
            if self.is_record_mode:
                self.piano_roll.start_recording(self.music_segment)
            self.pianorollWindow.setCentralWidget(self.piano_roll)

    def octaveDecrease(self):
        if self.octave > 0:
            self.octave = self.octave - 1
            self.octave_ctrl.setValue(self.octave)

            self.piano_roll = PianoRoll(self.player, self.volume, self.octave,
                                        (self.mode_type, self.mode_name),
                                        self.root_note_name, self.mode_display)
            if self.is_record_mode:
                self.piano_roll.start_recording(self.music_segment)
            self.pianorollWindow.setCentralWidget(self.piano_roll)

    def keyPressEvent(self, e):
        for group in range(2):
            for index in range(len(self.white_shortcuts[group])):
                if e.key() == self.white_shortcuts[group][index]:
                    self.player.note_on(
                        self.piano_roll.get_note('white', group, index),
                        self.volume)
                    self.piano_roll.keyPressed('white', group, index)
                    return

            for index in range(len(self.black_shortcuts[group])):
                if e.key() == self.black_shortcuts[group][index]:
                    self.player.note_on(
                        self.piano_roll.get_note('black', group, index),
                        self.volume)
                    self.piano_roll.keyPressed('black', group, index)
                    return

    def keyReleaseEvent(self, e):
        for group in range(2):
            for index in range(len(self.white_shortcuts[group])):
                if e.key() == self.white_shortcuts[group][index]:
                    self.player.note_off(
                        self.piano_roll.get_note('white', group, index),
                        self.volume)

                    self.piano_roll.keyRelease('white', group, index)

                    if self.is_record_mode:
                        self.music_segment.add_note(
                            self.piano_roll.get_note('white', group, index),
                            self.music_segment.length_per_note)
                        if self.music_segment.window_on == True:
                            self.music_segment.replot()
                    return

            for index in range(len(self.black_shortcuts[group])):
                if e.key() == self.black_shortcuts[group][index]:
                    self.player.note_off(
                        self.piano_roll.get_note('black', group, index),
                        self.volume)
                    self.piano_roll.keyRelease('black', group, index)

                    if self.is_record_mode:
                        self.music_segment.add_note(
                            self.piano_roll.get_note('black', group, index),
                            self.music_segment.length_per_note)
                        if self.music_segment.window_on == True:
                            self.music_segment.replot()
                    return
Beispiel #15
0
    class NumberBar(QWidget):
        '''
        使文本输入框能有行号,类种类哦!
        '''
        def __init__(self, editor):
            '''
            一些初始设置
            '''
            QWidget.__init__(self, editor)
            #NumberBar是类中类,故我们在初始化的时候也要把外部类的对象带进来

            self.editor = editor
            self.editor.blockCountChanged.connect(self.updateWidth)
            #每当块数(段落)发生变化时都会发出该信号并调用updateWidth()函数

            self.editor.updateRequest.connect(self.updateContents)
            #当文本文档需要更新指定的矩形时,会发出此信号

            self.font = QFont()
            self.numberBarColor = QColor("#e8e8e8")

        def paintEvent(self, event):
            '''
            重写小部件的绘图事件
            '''
            painter = QPainter(self)
            painter.fillRect(event.rect(), self.numberBarColor)
            # 构建一个绘画设备,并用指定的颜色填充给定的矩形。

            block = self.editor.firstVisibleBlock()
            # 返回第一个可见块,也就是文本块。

            while block.isValid():
                blockNumber = block.blockNumber()
                # 在文本块有效的情况下进入循环,返回此文本块的编号(行号),如果块无效,则返回-1。

                block_top = self.editor.blockBoundingGeometry(
                    block).translated(self.editor.contentOffset()).top()
                # 同时我们使用blockBoundingGeometry()函数以内容坐标返回文本块的边界矩形,并使用contentOffset()转义得到矩形以获得视口上的视觉坐标。这里得到top。

                if blockNumber == self.editor.textCursor().blockNumber():
                    self.font.setBold(True)
                    painter.setPen(QColor("#000000"))
                else:
                    self.font.setBold(False)
                    painter.setPen(QColor("#717171"))
                # 当鼠标移动到某一行的时候,其对应的行号会相应的变黑加粗

                paint_rect = QRect(0, block_top, self.width(),
                                   self.editor.fontMetrics().height())
                # 行号绘画的区域是paint_rect,这里使用QRect对象实现的;

                painter.drawText(paint_rect, Qt.AlignCenter,
                                 str(blockNumber + 1))
                # 居中对齐,具体的内容是str(blockNumber+1),不加1就是0开始了。

                block = block.next()

        def getWidth(self):
            '''
            返回显示行号的小部件宽度
            '''
            count = self.editor.blockCount()
            # 保存文档中文本块的数量

            if 0 <= count < 99999:
                width = self.fontMetrics().width('99999')
            else:
                width = self.fontMetrics().width(str(count))
            return width
            # 如果行数小于99999行,那么返回小部件当前字体的字体的宽度,这个宽度是内容’99999’的字体宽度。否则就返回实际宽度。

        def updateWidth(self):
            '''
            显示行号位置的实际宽度
            '''
            width = self.getWidth()
            self.editor.setViewportMargins(width, 0, 0, 0)
            #通过setViewportMargins设置编辑器显示行号位置的实际宽度

        def updateContents(self, rect, dy):
            '''
            重新绘制小部件区域
            '''
            if dy:
                self.scroll(0, dy)
            # 如果存在垂直滚动,且像素dy > 0,那么将小部件向下滚动。滚动后,小部件将接收需要重新绘制区域的绘画事件。
            else:
                self.update(0, rect.y(), self.width(), rect.height())
            # 否则更新小部件内的矩形(x,y,w,h)。

            if rect.contains(self.editor.viewport().rect()):
                # 判断编辑器视口的矩形是否在rect这个矩形内。
                fontSize = self.editor.currentCharFormat().font().pointSize()
                self.font.setPointSize(fontSize)
                self.font.setStyle(QFont.StyleNormal)
                self.updateWidth()
Beispiel #16
0
class NumberBar(QWidget):
    def __init__(self, editor):
        QWidget.__init__(self, editor)
        self.editor = editor
        self.editor.blockCountChanged.connect(self.updateWidth)
        self.editor.updateRequest.connect(self.updateContents)
        self.font = QFont()
        self.numberBarColor = QColor("#e8e8e8")
        self.currentLineNumber = None
        self.editor.cursorPositionChanged.connect(self.highligtCurrentLine)
        self.highligtCurrentLine()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(event.rect(), self.numberBarColor)
        block = self.editor.firstVisibleBlock()

        while block.isValid():
            blockNumber = block.blockNumber()
            block_top = self.editor.blockBoundingGeometry(block).translated(self.editor.contentOffset()).top()
            if blockNumber == self.editor.textCursor().blockNumber():
                self.font.setBold(True)
                painter.setPen(QColor("#000000"))
            else:
                self.font.setBold(False)
                painter.setPen(QColor("#717171"))
            paint_rect = QRect(0, block_top, self.width(), self.editor.fontMetrics().height())
            painter.drawText(paint_rect, Qt.AlignCenter, str(blockNumber + 1))
            block = block.next()

    def getWidth(self):
        count = self.editor.blockCount()
        if 0 <= count < 99999:
            width = self.fontMetrics().width('99999')
        else:
            width = self.fontMetrics().width(str(count))
        return width

    def updateWidth(self):
        width = self.getWidth()
        self.editor.setViewportMargins(width, 0, 0, 0)

    def updateContents(self, rect, dy):
        if dy:
            self.scroll(0, dy)
        else:
            self.update(0, rect.y(), self.width(), rect.height())
        if rect.contains(self.editor.viewport().rect()):
            fontSize = self.editor.currentCharFormat().font().pointSize()
            self.font.setPointSize(fontSize)
            self.font.setStyle(QFont.StyleNormal)
            self.updateWidth()

    def highligtCurrentLine(self):
        newCurrentLineNumber = self.editor.textCursor().blockNumber()
        if newCurrentLineNumber != self.currentLineNumber:
            lineColor = QColor(Qt.yellow).lighter(160)
            self.currentLineNumber = newCurrentLineNumber
            hi_selection = QTextEdit.ExtraSelection()
            hi_selection.format.setBackground(lineColor)
            hi_selection.format.setProperty(QTextFormat.FullWidthSelection, True)
            hi_selection.cursor = self.editor.textCursor()
            hi_selection.cursor.clearSelection()
            self.editor.setExtraSelections([hi_selection])

    def resize(self,mm):
        self.cr = mm.contentsRect()
        # print(self.cr.left(),self.cr.top(),self.getWidth(),self.cr.height())
        rec = QRect(self.cr.left(), self.cr.top(), self.getWidth(), self.cr.height())
        self.setGeometry(rec)
Beispiel #17
0
def read_css(css):
    if not HAS_TINYCSS2 or css is None:
        return

    try:
        with open(css, 'r') as f:
            sheet = tinycss2.parse_stylesheet(''.join(f.readlines()))
    except FileNotFoundError:
        return

    stylename = None
    node = {
        'bgcolor': {
            'normal': Qt.lightGray,
            'selected': QColor()
        },
        'txtcolor': {
            'normal': Qt.black,
            'selected': QColor()
        },
        'border': {
            'normal': {
                'style': Qt.SolidLine,
                'width': 1,
                'color': 'black'
            },
            'selected': {
                'style': Qt.SolidLine,
                'width': 1,
                'color': 'black'
            }
        },
        'font': {
            'normal': {
                'family': 'Arial',
                'variant': QFont.MixedCase,
                'size': 10,
                'unit': 'pt',
                'style': QFont.StyleNormal,
                'weight': QFont.Normal
            },
            'selected': {
                'family': 'Arial',
                'variant': QFont.MixedCase,
                'size': 10,
                'unit': 'pt',
                'style': QFont.StyleNormal,
                'weight': QFont.Normal
            }
        }
    }
    edge = {'color': {'normal': Qt.darkGray, 'selected': Qt.red}}
    scene = {'color': Qt.white}

    for rule in sheet:
        if rule.type == 'comment' and stylename is None:
            try:
                stylename = rule.value.split('name: ')[1].strip()
            except IndexError:
                stylename = ""
        elif rule.type == 'qualified-rule':
            for name, state, prop, token in parse_rule(rule):
                if name == 'node':
                    if token.type == 'ident':
                        if prop == 'background-color':
                            node['bgcolor'][state] = token.value
                        elif prop == 'color':
                            node['txtcolor'][state] = token.value
                        elif prop == 'font-family':
                            node['font'][state]['family'] = token.value
                        elif prop == 'font-weight':
                            weight = css_font_weight_to_qt(token.value)
                            if weight is not None:
                                node['font'][state]['weight'] = weight
                        elif prop == 'font-style':
                            style = CSS_FONT_STYLES_TO_QT.get(token.value)
                            if style is not None:
                                node['font'][state]['style'] = style
                        elif prop == 'font-variant':
                            variant = CSS_FONT_VARIANTS_TO_QT.get(token.value)
                            node['font'][state]['variant'] = variant
                        elif prop == 'font':
                            style = CSS_FONT_STYLES_TO_QT.get(token.value)
                            if style is not None:
                                node['font'][state]['style'] = style
                            else:
                                variant = CSS_FONT_VARIANTS_TO_QT.get(
                                    token.value)
                                if variant is not None:
                                    node['font'][state]['variant'] = variant
                                else:
                                    weight = css_font_weight_to_qt(token.value)
                                    if weight is not None:
                                        node['font'][state]['weight'] = weight
                                    else:
                                        node['font'][state][
                                            'family'] = token.value
                        elif prop == 'border-style':
                            style = CSS_BORDER_STYLES_TO_QT.get(token.value)
                            node['border'][state]['style'] = style
                        elif prop == 'border-color':
                            node['border'][state]['color'] = token.value
                        elif prop == 'border':
                            style = CSS_BORDER_STYLES_TO_QT.get(token.value)
                            if style is not None:
                                node['border'][state]['style'] = style
                            else:
                                node['border'][state]['color'] = token.value
                    elif token.type == 'dimension':
                        if prop in ('font', 'font-size'):
                            node['font'][state]['size'] = token.value
                            node['font'][state]['unit'] = token.unit
                        elif prop in ('border', 'border-width'):
                            node['border'][state]['width'] = token.value
                    elif token.type == 'hash':
                        if prop == 'background-color':
                            node['bgcolor'][state] = token.serialize()
                        elif prop == 'color':
                            node['txtcolor'][state] = token.serialize()
                        elif prop in ('border', 'border-color'):
                            node['border'][state]['color'] = token.serialize()
                elif name == 'edge':
                    if token.type == 'ident':
                        if prop == 'background-color':
                            edge['color'][state] = token.value
                    elif token.type == 'hash':
                        if prop == 'background-color':
                            edge['color'][state] = token.serialize()
                elif name == 'scene':
                    if token.type == 'ident':
                        if prop == 'background-color':
                            scene['color'] = token.value
                    elif token.type == 'hash':
                        if prop == 'background-color':
                            scene['color'] = token.serialize()

    for state in ('normal', 'selected'):
        node['bgcolor'][state] = QBrush(QColor(node['bgcolor'][state]))
        node['txtcolor'][state] = QColor(node['txtcolor'][state])
        node['border'][state] = QPen(
            QBrush(QColor(node['border'][state]['color'])),
            node['border'][state]['width'], node['border'][state]['style'])
        f = QFont(node['font'][state]['family'])
        if node['font'][state]['unit'] == 'px':
            f.setPixelSize(node['font'][state]['size'])
        else:
            f.setPointSize(node['font'][state]['size'])
        f.setCapitalization(node['font'][state]['variant'])
        f.setWeight(node['font'][state]['weight'])
        f.setStyle(node['font'][state]['style'])
        node['font'][state] = f
        edge['color'][state] = QPen(QColor(edge['color'][state]))
    scene['color'] = QColor(scene['color'])

    return stylename, node, edge, scene
    class NumberBar(QWidget):
        '''
        使文本输入框能有行号,类种类哦!
        '''

        #win_slip = pyqtSignal(top, end)

        def __init__(self, editor):
            '''
            一些初始设置
            '''
            QWidget.__init__(self, editor)
            # NumberBar是类中类,故我们在初始化的时候也要把外部类的对象带进来

            self.editor = editor
            self.editor.blockCountChanged.connect(self.updateWidth)
            # 每当块数(段落)发生变化时都会发出该信号并调用updateWidth()函数

            self.editor.updateRequest.connect(self.updateContents)
            # 当文本文档需要更新指定的矩形时,会发出此信号

            self.font = QFont()
            self.numberBarColor = QColor("#e8e8e8")

        def visibleBlockInfo(self):
            block = self.editor.firstVisibleBlock()
            topBlockNum = block.blockNumber()
            blockCount = self.editor.blockCount()
            while block.isValid():
                endBlockNum = block.blockNumber()
                block = block.next()

            return blockCount, topBlockNum, endBlockNum

        def paintEvent(self, event):
            '''
            重写小部件的绘图事件
            '''
            painter = QPainter(self)
            painter.fillRect(event.rect(), self.numberBarColor)
            # 构建一个绘画设备,并用指定的颜色填充给定的矩形。

            block = self.editor.firstVisibleBlock()
            '''
            blockCount, topBlockNum, endBlockNum = self.visibleBlockInfo()
            print ("blockCount:", blockCount)
            print ("topBlockNum:", topBlockNum)
            print("endBlockNum:", endBlockNum)
            '''

            #print ("firstBlock:", self.editor.firstBlock())
            # 返回第一个可见块,也就是文本块。

            while block.isValid():
                blockNumber = block.blockNumber()
                # 在文本块有效的情况下进入循环,返回此文本块的编号(行号),如果块无效,则返回-1。

                block_top = self.editor.blockBoundingGeometry(
                    block).translated(self.editor.contentOffset()).top()
                # 同时我们使用blockBoundingGeometry()函数以内容坐标返回文本块的边界矩形,并使用contentOffset()转义得到矩形以获得视口上的视觉坐标。这里得到top。

                if blockNumber == self.editor.textCursor().blockNumber():
                    self.font.setBold(True)
                    painter.setPen(QColor("#000000"))
                else:
                    self.font.setBold(False)
                    painter.setPen(QColor("#1E90FF"))
                # 当鼠标移动到某一行的时候,其对应的行号会相应的变黑加粗

                paint_rect = QRect(0, block_top, self.width(),
                                   self.editor.fontMetrics().height())
                # 行号绘画的区域是paint_rect,这里使用QRect对象实现的;

                str = "%.8x    " % (blockNumber * 16)
                #str = "%.8d    " % (blockNumber)
                hexs = self.editor.document().findBlockByLineNumber(
                    blockNumber).text()
                hex_list = hexs.split(" ")
                #print (len(hex_list), hex_list)
                #HEX字符串转ANSICII字符
                for each_hex in hex_list:
                    if (each_hex == ''):
                        break
                    if (len(each_hex) % 2 != 0):
                        each_hex = '0' + each_hex
                    try:
                        hex_val = each_hex.encode('utf-8')
                        str_bin = binascii.unhexlify(hex_val)
                        ansicii_str = str_bin.decode('utf-8')
                    except:
                        ansicii_str = '.'
                    #print (ansicii_str)
                    str += ansicii_str
                painter.drawText(paint_rect, Qt.AlignLeft, str)
                # 居中对齐,具体的内容是str(blockNumber+1),不加1就是0开始了。

                block = block.next()

        def getWidth(self):
            '''
            返回显示行号的小部件宽度
            '''
            count = self.editor.blockCount()
            # 保存文档中文本块的数量
            """
            if 0 <= count < 99999:
                width = self.fontMetrics().width('99999')
            else:
                width = self.fontMetrics().width(str(count))
            """
            width = self.fontMetrics().width('ffffffff    1234567812345678')
            return width
            # 如果行数小于99999行,那么返回小部件当前字体的字体的宽度,这个宽度是内容’99999’的字体宽度。否则就返回实际宽度。

        def updateWidth(self):
            '''
            显示行号位置的实际宽度
            '''
            width = self.getWidth()
            self.editor.setViewportMargins(width, 0, 0, 0)
            # 通过setViewportMargins设置编辑器显示行号位置的实际宽度

        def updateContents(self, rect, dy):
            '''
            重新绘制小部件区域
            '''
            if dy:
                self.scroll(0, dy)
            # 如果存在垂直滚动,且像素dy > 0,那么将小部件向下滚动。滚动后,小部件将接收需要重新绘制区域的绘画事件。
            else:
                self.update(0, rect.y(), self.width(), rect.height())
            # 否则更新小部件内的矩形(x,y,w,h)。

            if rect.contains(self.editor.viewport().rect()):
                # 判断编辑器视口的矩形是否在rect这个矩形内。
                fontSize = self.editor.currentCharFormat().font().pointSize()
                self.font.setPointSize(fontSize)
                self.font.setStyle(QFont.StyleNormal)
                self.updateWidth()

        def find_loc_block(self, y):
            block = self.editor.firstVisibleBlock()
            # 返回第一个可见块,也就是文本块。
            while block.isValid():
                # 在文本块有效的情况下进入循环,返回此文本块的编号(行号),如果块无效,则返回-1。
                block_top = self.editor.blockBoundingGeometry(
                    block).translated(self.editor.contentOffset()).top()
                # 同时我们使用blockBoundingGeometry()函数以内容坐标返回文本块的边界矩形,并使用contentOffset()转义得到矩形以获得视口上的视觉坐标。这里得到top。

                if (y >= block_top and y <=
                    (block_top + self.editor.fontMetrics().height())):
                    return block.text()

                block = block.next()
            return None