Пример #1
0
    def set_px_per_beat(self, px_per_beat):
        if self._px_per_beat != px_per_beat:
            orig_px_per_beat = self._px_per_beat
            orig_px_offset = self._px_offset

            self._px_per_beat = px_per_beat

            if not self._ui_model:
                return

            # Get old edit cursor offset
            grid_mgr = self._ui_model.get_grid_manager()
            selected_line_ts = tstamp.Tstamp(0)
            gp_id = grid_mgr.get_selected_grid_pattern_id()
            if gp_id != None:
                gp = grid_mgr.get_grid_pattern(gp_id)
                selected_line_ts = gp.get_selected_line() or tstamp.Tstamp(0)
            orig_relative_offset = utils.get_px_from_tstamp(
                selected_line_ts, orig_px_per_beat) - orig_px_offset

            # Adjust vertical position so that edit cursor maintains its height
            new_cursor_offset = utils.get_px_from_tstamp(
                selected_line_ts, px_per_beat)
            new_px_offset = new_cursor_offset - orig_relative_offset
            self.followCursor.emit(str(new_px_offset))
Пример #2
0
def get_tstamp_from_px(px, px_per_beat):
    beats = px // px_per_beat
    rem_px = px % px_per_beat
    rem = rem_px * tstamp.BEAT // px_per_beat
    if rem * px_per_beat < rem_px * tstamp.BEAT:
        rem += 1
    return tstamp.Tstamp(beats, rem)
Пример #3
0
    def _follow_edit_cursor(self):
        grid_mgr = self._ui_model.get_grid_manager()
        gp_id = grid_mgr.get_selected_grid_pattern_id()
        if gp_id == None:
            return
        gp = grid_mgr.get_grid_pattern(gp_id)

        selected_line_ts = gp.get_selected_line() or tstamp.Tstamp(0)
        cursor_abs_y = utils.get_px_from_tstamp(selected_line_ts,
                                                self._px_per_beat)
        cursor_rel_y = cursor_abs_y - self._px_offset

        is_scrolling_required = False

        min_snap_dist = self._config['edit_cursor']['min_snap_dist']
        min_centre_dist = min(min_snap_dist, self.height() // 2)
        min_y_offset = min_centre_dist
        max_y_offset = self.height() - min_centre_dist

        if cursor_rel_y < min_centre_dist:
            is_scrolling_required = True
            new_px_offset = self._px_offset - (min_y_offset - cursor_rel_y)
        elif cursor_rel_y >= max_y_offset:
            is_scrolling_required = True
            new_px_offset = self._px_offset + (cursor_rel_y - max_y_offset)

        if is_scrolling_required:
            self.followCursor.emit(str(new_px_offset))

        self.update()
Пример #4
0
 def _move_edit_cursor_to_playback_cursor(self):
     (track, system, row) = self._session.get_playback_cursor_position()
     selection = self._ui_model.get_selection()
     current_location = selection.get_location()
     col_num = current_location.get_col_num()
     row_ts = tstamp.Tstamp(*row)
     new_location = TriggerPosition(track, system, col_num, row_ts, 0)
     selection.set_location(new_location)
Пример #5
0
    def test_beat_is_divided_optimally(self):
        for px_per_beat in range(1, 300):
            offsets = [
                utils.get_tstamp_from_px(offset, px_per_beat)
                for offset in range(px_per_beat)
            ]
            self.assertEqual(offsets[0], 0)
            expected_px = 0
            lens = set()
            for start, stop in zip_longest(offsets, islice(offsets, 1, None)):
                if stop == None:
                    stop = tstamp.Tstamp(1, 0)
                end = stop - tstamp.Tstamp(0, 1)
                start_px = utils.get_px_from_tstamp(start, px_per_beat)
                end_px = utils.get_px_from_tstamp(end, px_per_beat)

                self.assertEqual(
                    expected_px,
                    start_px,
                    msg='start_px {} did not match expected_px {},'
                    ' px_per_beat: {}'.format(start_px, expected_px,
                                              px_per_beat))
                self.assertEqual(
                    start_px,
                    end_px,
                    msg=
                    '{} and {} resulted in different pixel offsets {} and {},'
                    ' px_per_beat: {}'.format(start, end, start_px, end_px,
                                              px_per_beat))
                interval_len = end - start
                self.assertTrue(
                    interval_len in lens or len(lens) < 2,
                    msg='Found third interval length {} at [{}, {}],'
                    ' existing: {}, px_per_beat: {}'.format(
                        interval_len, start, end, lens, px_per_beat))

                lens.add(interval_len)
                expected_px += 1

            lens_list = list(lens)
            if len(lens_list) == 2:
                self.assertTrue(
                    abs(lens_list[0] - lens_list[1]) == tstamp.Tstamp(0, 1),
                    msg='Incorrect lengths: {}, px_per_beat: {}'.format(
                        lens_list, px_per_beat))
Пример #6
0
    def _change_offset(self, new_offset):
        new_offset_ts = tstamp.Tstamp(new_offset)

        gp = self._get_selected_grid_pattern()
        if gp == None:
            return

        gp.set_offset(new_offset_ts)
        self._updater.signal_update('signal_grid_pattern_modified')
Пример #7
0
    def _change_length(self, new_length):
        new_length_ts = tstamp.Tstamp(new_length)

        gp = self._get_selected_grid_pattern()
        if gp == None:
            return

        gp.set_length(new_length_ts)
        self._updater.signal_update(set(['signal_grid_pattern_modified']))
Пример #8
0
    def _change_value(self, new_value, is_final):
        pattern = self._get_pattern()
        if not pattern:
            return

        sheet_mgr = self._ui_model.get_sheet_manager()

        length = tstamp.Tstamp(new_value)
        if length == pattern.get_length():
            if is_final and not self._is_latest_committed:
                sheet_mgr.set_pattern_length(pattern, length, is_final)
                self._is_latest_committed = True
            return

        sheet_mgr.set_pattern_length(pattern, length, is_final)
        self._updater.signal_update('signal_pattern_length')
Пример #9
0
    def _change_grid_pattern(self, index):
        gp_id = self.itemData(index)
        if not gp_id:
            return

        pinst = self._get_pattern_instance()
        if not pinst:
            return

        offset = tstamp.Tstamp(0)  # TODO

        pattern = pinst.get_pattern()

        sheet_mgr = self._ui_model.get_sheet_manager()

        selection = self._ui_model.get_selection()
        if selection.has_rect_area():
            top_left = selection.get_area_top_left()
            bottom_right = selection.get_area_bottom_right()
            start_col = top_left.get_col_num()
            stop_col = bottom_right.get_col_num() + 1
            start_ts = top_left.get_row_ts()
            stop_ts = bottom_right.get_row_ts()

            pat_length = pattern.get_length()
            full_columns_selected = ((start_ts == tstamp.Tstamp(0))
                                     and (stop_ts > pat_length))
            all_selected = (full_columns_selected
                            and ((start_col, stop_col) == (0, COLUMNS_MAX)))

            if all_selected:
                sheet_mgr.set_pattern_base_grid_pattern_id(pattern,
                                                           gp_id,
                                                           is_final=False)

            if all_selected or (gp_id == pattern.get_base_grid_pattern_id()):
                gp_id = None

            if (full_columns_selected
                    and (pattern.get_base_grid_pattern_id() == gp_id)
                    and (pattern.get_base_grid_pattern_offset() == offset)):
                sheet_mgr.clear_overlay_grids(pinst, start_col, stop_col)
            else:
                sheet_mgr.set_overlay_grid(pinst, start_col, stop_col,
                                           start_ts, stop_ts, gp_id, offset)

        else:
            location = selection.get_location()
            col_num = location.get_col_num()
            column = pinst.get_column(location.get_col_num())
            start_ts, stop_ts = column.get_overlay_grid_range_at(
                location.get_row_ts())
            col_gp_id, offset = column.get_overlay_grid_info_at(
                location.get_row_ts())

            if col_gp_id != None:
                pat_length = pattern.get_length()
                full_column_selected = ((start_ts == tstamp.Tstamp(0))
                                        and (stop_ts > pat_length))
                if (full_column_selected
                        and (pattern.get_base_grid_pattern_id() == gp_id) and
                    (pattern.get_base_grid_pattern_offset() == offset)):
                    sheet_mgr.clear_overlay_grids(pinst, col_num, col_num + 1)
                else:
                    if gp_id == pattern.get_base_grid_pattern_id():
                        gp_id = None
                    sheet_mgr.set_overlay_grid(pinst, col_num, col_num + 1,
                                               start_ts, stop_ts, gp_id,
                                               offset)

            else:
                sheet_mgr.set_pattern_base_grid_pattern_id(pattern,
                                                           gp_id,
                                                           is_final=True)

        self._updater.signal_update('signal_grid')
Пример #10
0
    def _create_pixmap(self, index, grid):
        pixmap = QPixmap(self._width, ColumnCache.PIXMAP_HEIGHT)

        painter = QPainter(pixmap)

        # Background
        painter.setBackground(self._get_final_colour(self._config['bg_colour']))
        painter.eraseRect(QRect(0, 0, self._width - 1, ColumnCache.PIXMAP_HEIGHT))

        # Start and stop timestamps
        start_px = index * ColumnCache.PIXMAP_HEIGHT
        stop_px = (index + 1) * ColumnCache.PIXMAP_HEIGHT

        visible_tr_start_px = start_px - self._config['tr_height'] + 1
        start_ts = tstamp.Tstamp(0,
                visible_tr_start_px * tstamp.BEAT // self._px_per_beat)
        stop_ts = tstamp.Tstamp(0,
                stop_px * tstamp.BEAT // self._px_per_beat)

        def ts_to_y_offset(ts):
            rems = ts.beats * tstamp.BEAT + ts.rem
            abs_y = rems * self._px_per_beat // tstamp.BEAT
            y_offset = abs_y - start_px
            return y_offset

        # Grid
        sheet_manager = self._ui_model.get_sheet_manager()
        if sheet_manager.is_grid_enabled():
            pinsts = utils.get_all_pattern_instances(self._ui_model)
            pinst = pinsts[self._pat_index]

            grid_start_ts = tstamp.Tstamp(0, start_px * tstamp.BEAT // self._px_per_beat)
            tr_height_ts = utils.get_tstamp_from_px(
                    self._config['tr_height'], self._px_per_beat)
            lines = grid.get_grid_lines(
                    pinst, self._col_num, grid_start_ts, stop_ts, tr_height_ts)

            for line_info in lines:
                line_ts, line_style = line_info
                line_y_offset = ts_to_y_offset(line_ts)

                line_pixmap = self._gl_cache.get_line_pixmap(line_style)
                painter.drawPixmap(QPoint(0, line_y_offset), line_pixmap)

        # Trigger rows
        painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
        for ts, image, next_ts in self._tr_cache.iter_images(start_ts, stop_ts):
            y_offset = ts_to_y_offset(ts)

            src_rect = image.rect()
            dest_rect = src_rect.translated(QPoint(0, y_offset))

            if next_ts != None:
                next_y_offset = ts_to_y_offset(next_ts)
                y_dist = next_y_offset - y_offset
                if y_dist < dest_rect.height():
                    rect_height = max(1, y_dist)
                    dest_rect.setHeight(rect_height)
                    src_rect.setHeight(rect_height)

            painter.drawImage(dest_rect, image, src_rect)

        # Border
        painter.setPen(self._get_final_colour(self._config['border_colour']))
        painter.drawLine(
                QPoint(self._width - 1, 0),
                QPoint(self._width - 1, ColumnCache.PIXMAP_HEIGHT))

        # Testing
        """
        painter.setBackground(Qt.black)
        painter.eraseRect(QRect(0, 0, self._width, ColumnCache.PIXMAP_HEIGHT))
        painter.setPen(Qt.white)
        painter.drawRect(0, 0, self._width - 1, ColumnCache.PIXMAP_HEIGHT - 1)
        pixmap_desc = '{}-{}-{}'.format(self._col_num, self._pat_index, index)
        painter.drawText(QPoint(2, 12), pixmap_desc)
        """

        return pixmap
Пример #11
0
    def _create_pixmap(self, index):
        pixmap = QPixmap(self._width, RulerCache.PIXMAP_HEIGHT)

        cfg = self._config

        painter = QPainter(pixmap)

        # Background
        painter.setBackground(self._get_final_colour(cfg['bg_colour']))
        painter.eraseRect(
            QRect(0, 0, self._width - 1, RulerCache.PIXMAP_HEIGHT))
        painter.setPen(self._get_final_colour(cfg['fg_colour']))
        painter.drawLine(QPoint(self._width - 1, 0),
                         QPoint(self._width - 1, RulerCache.PIXMAP_HEIGHT - 1))

        # Start border
        if index == 0:
            painter.drawLine(QPoint(0, 0), QPoint(self._width - 2, 0))

        # Ruler lines
        start_ts = tstamp.Tstamp(
            0, tstamp.BEAT * index * RulerCache.PIXMAP_HEIGHT //
            self._px_per_beat)
        stop_ts = tstamp.Tstamp(
            0,
            tstamp.BEAT * (index + 1) * RulerCache.PIXMAP_HEIGHT //
            self._px_per_beat)

        def draw_ruler_line(painter, y, line_pos, lines_per_beat):
            line_length = (cfg['line_len_long']
                           if line_pos[1] == 0 else cfg['line_len_short'])
            painter.drawLine(QPoint(self._width - 1 - line_length, y),
                             QPoint(self._width - 1, y))

        self._draw_markers(painter, start_ts, stop_ts, cfg['line_min_dist'],
                           draw_ruler_line)

        # Beat numbers
        num_extent = self._num_height // 2
        start_ts = tstamp.Tstamp(
            0,
            tstamp.BEAT * (index * RulerCache.PIXMAP_HEIGHT - num_extent) //
            self._px_per_beat)
        stop_ts = tstamp.Tstamp(
            0,
            tstamp.BEAT *
            ((index + 1) * RulerCache.PIXMAP_HEIGHT + num_extent) //
            self._px_per_beat)

        text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter)

        def draw_number(painter, y, num_pos, nums_per_beat):
            if num_pos == [0, 0]:
                return

            # Text
            num = num_pos[0] + num_pos[1] / float(nums_per_beat)
            numi = int(num)
            text = str(numi) if num == numi else str(round(num, 3))

            # Draw
            rect = QRectF(0, y - self._num_height,
                          self._width - cfg['line_len_long'] - 2,
                          self._num_height + 3)
            painter.drawText(rect, text, text_option)

        painter.setFont(self._config['font'])
        self._draw_markers(painter, start_ts, stop_ts, cfg['num_min_dist'],
                           draw_number)

        # Draw pixmap index for debugging
        #painter.drawText(QPoint(2, 12), str(index))

        return pixmap
Пример #12
0
    def _draw_markers(self, painter, start_ts, stop_ts, min_dist, draw_fn):
        cfg = self._config

        beat_div_base = 2

        if min_dist <= self._px_per_beat:
            markers_per_beat = self._px_per_beat // min_dist
            markers_per_beat = int(beat_div_base**math.floor(
                math.log(markers_per_beat, beat_div_base)))

            # First visible marker in the first beat
            start_beat_frac = start_ts.rem / float(tstamp.BEAT)
            start_marker_in_beat = int(
                math.ceil(start_beat_frac * markers_per_beat))

            # First non-visible marker in the last beat
            stop_beat_frac = stop_ts.rem / float(tstamp.BEAT)
            stop_marker_in_beat = int(
                math.ceil(stop_beat_frac * markers_per_beat))

            def normalise_marker_pos(pos):
                excess = pos[1] // markers_per_beat
                pos[0] += excess
                pos[1] -= excess * markers_per_beat
                assert pos[1] >= 0
                assert pos[1] < markers_per_beat

            # Loop boundaries
            marker_pos = [start_ts.beats, start_marker_in_beat]
            normalise_marker_pos(marker_pos)

            stop_pos = [stop_ts.beats, stop_marker_in_beat]
            normalise_marker_pos(stop_pos)

            # Draw markers
            while marker_pos < stop_pos:
                ts = tstamp.Tstamp(marker_pos[0] +
                                   marker_pos[1] / float(markers_per_beat))
                y = float(ts - start_ts) * self._px_per_beat

                draw_fn(painter, y, marker_pos, markers_per_beat)

                # Next marker
                marker_pos[1] += 1
                normalise_marker_pos(marker_pos)

        else:
            # Zoomed far out -- skipping whole beats
            beats_per_marker = (min_dist + self._px_per_beat -
                                1) // self._px_per_beat
            beats_per_marker = int(beat_div_base**math.ceil(
                math.log(beats_per_marker, beat_div_base)))

            # First beat with a visible marker
            start_beat = (start_ts - tstamp.Tstamp(0, 1)).beats + 1
            start_marker_in_beat = beats_per_marker * int(
                math.ceil(start_beat / float(beats_per_marker)))

            # First non-visible beat
            stop_beat = (stop_ts - tstamp.Tstamp(0, 1)).beats + 1

            # Draw markers
            for marker_pos in range(start_marker_in_beat, stop_beat,
                                    beats_per_marker):
                y = float(marker_pos - start_ts) * self._px_per_beat
                draw_fn(painter, y, [marker_pos, 0], 1)
Пример #13
0
 def _change_tstamp_value(self):
     new_str = self._editors[tstamp.Tstamp].text()
     new_value = tstamp.Tstamp(float(new_str))
     self._change_value(new_value)
Пример #14
0
    def _change_tstamp_value(self):
        value = tstamp.Tstamp(float(self._editors[tstamp.Tstamp].text()))

        playback_mgr = self._ui_model.get_playback_manager()
        playback_mgr.set_runtime_var_value(self._var_name, value)
Пример #15
0
    def _create_pixmap(self, index):
        pixmap = QPixmap(self._width, RulerCache.PIXMAP_HEIGHT)

        cfg = self._config

        painter = QPainter(pixmap)

        # Background
        painter.setBackground(self._get_final_colour(cfg['bg_colour']))
        painter.eraseRect(QRect(0, 0, self._width, RulerCache.PIXMAP_HEIGHT))

        # Lines
        painter.save()

        line_width = cfg['line_width']
        line_pen = QPen(self._get_final_colour(cfg['fg_colour']))
        line_pen.setWidthF(line_width)
        painter.setPen(line_pen)
        painter.translate(0, -((line_width - 1) // 2))

        painter.drawLine(
                QPoint(self._width - line_width / 2, 0),
                QPoint(self._width - line_width / 2, RulerCache.PIXMAP_HEIGHT - 1))

        # Ruler lines
        slice_margin_ts = utils.get_tstamp_from_px(line_width / 2, self._px_per_beat)

        start_ts = tstamp.Tstamp(0, tstamp.BEAT *
                index * RulerCache.PIXMAP_HEIGHT // self._px_per_beat)
        stop_ts = tstamp.Tstamp(0, tstamp.BEAT *
                (index + 1) * RulerCache.PIXMAP_HEIGHT // self._px_per_beat)

        def draw_ruler_line(painter, y, line_pos, lines_per_beat):
            if line_pos[1] == 0:
                line_length = cfg['line_len_long'] if line_pos[0] != 0 else self._width
            else:
                line_length = cfg['line_len_short']
            painter.drawLine(
                    QPoint(self._width - 1 - line_length, y),
                    QPoint(self._width - 1, y))

        self._draw_markers(
                painter,
                start_ts - slice_margin_ts,
                stop_ts + slice_margin_ts,
                cfg['line_min_dist'],
                draw_ruler_line)

        painter.restore()

        # Beat numbers
        painter.setPen(self._get_final_colour(cfg['fg_colour']))

        num_extent = self._num_height // 2
        start_ts = tstamp.Tstamp(0, tstamp.BEAT *
                (index * RulerCache.PIXMAP_HEIGHT - num_extent) //
                self._px_per_beat)
        stop_ts = tstamp.Tstamp(0, tstamp.BEAT *
                ((index + 1) * RulerCache.PIXMAP_HEIGHT + num_extent) //
                self._px_per_beat)

        text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter)

        def draw_number(painter, y, num_pos, nums_per_beat):
            if num_pos == [0, 0]:
                return

            # Text
            num = num_pos[0] + num_pos[1] / float(nums_per_beat)
            numi = int(num)
            text = str(numi) if num == numi else str(round(num, 3))

            # Draw
            right_offset = cfg['line_len_long'] + cfg['num_padding_right']
            rect = QRectF(0, y - self._num_height,
                    self._width - right_offset, self._num_height + 3)
            painter.drawText(rect, text, text_option)

        painter.setFont(self._config['font'])
        self._draw_markers(
                painter,
                start_ts,
                stop_ts,
                cfg['num_min_dist'],
                draw_number)

        # Draw pixmap index for debugging
        #painter.drawText(QPoint(2, 12), str(index))

        return pixmap
Пример #16
0
    def paintEvent(self, event):
        start = time.time()

        painter = QPainter(self)

        # Background
        painter.setBackground(self._config['canvas_bg_colour'])
        painter.eraseRect(QRect(0, 0, self._width, self.height()))

        # Get grid pattern info
        grid_mgr = self._ui_model.get_grid_manager()
        gp_id = grid_mgr.get_selected_grid_pattern_id()
        if gp_id == None:
            return
        gp = grid_mgr.get_grid_pattern(gp_id)

        gp_length = gp.get_length()
        gp_lines = gp.get_lines()
        selected_line_ts = gp.get_selected_line()

        # Column background
        painter.setBackground(self._config['bg_colour'])
        length_rems = gp_length.beats * tstamp.BEAT + gp_length.rem
        height_px = length_rems * self._px_per_beat // tstamp.BEAT
        bg_extent = height_px - self._px_offset
        painter.eraseRect(QRect(0, 0, self._width, bg_extent))

        # Grid lines
        selected_line_found = False
        for line in gp_lines:
            line_ts_raw, line_style = line

            line_ts = tstamp.Tstamp(line_ts_raw)
            if line_ts >= gp_length:
                continue

            abs_y = utils.get_px_from_tstamp(line_ts, self._px_per_beat)
            y_offset = abs_y - self._px_offset
            if not 0 <= y_offset < self.height():
                continue

            pen = QPen(self._config['grid']['styles'][line_style])
            painter.setPen(pen)
            painter.drawLine(QPoint(0, y_offset),
                             QPoint(self._width - 1, y_offset))

            if line_ts == selected_line_ts:
                selected_line_found = True

        if selected_line_found:
            cursor_config = self._config['grid']['edit_cursor']
            cursor_max_y = (cursor_config['height'] - 1) // 2

            abs_y = utils.get_px_from_tstamp(selected_line_ts,
                                             self._px_per_beat)
            y_offset = abs_y - self._px_offset

            painter.setRenderHint(QPainter.Antialiasing)
            painter.translate(QPointF(0.5, 0.5 + y_offset))
            painter.setPen(cursor_config['colour'])
            painter.setBrush(cursor_config['colour'])
            painter.drawPolygon(
                QPolygon([
                    QPoint(0, cursor_max_y),
                    QPoint(cursor_config['width'], 0),
                    QPoint(0, -cursor_max_y)
                ]))

        end = time.time()
        elapsed = end - start
Пример #17
0
def get_pat_height(length, px_per_beat):
    return int(math.ceil(float(length + tstamp.Tstamp(0, 1)) * px_per_beat))
Пример #18
0
    def _create_pixmap(self, index, grid):
        pixmap = QPixmap(self._width, ColumnCache.PIXMAP_HEIGHT)

        painter = QPainter(pixmap)

        album = self._ui_model.get_module().get_album()
        track, system = album.get_pattern_instance_location_by_nums(*self._pinst_ref)
        pat_index = utils.get_pattern_index_at_location(self._ui_model, track, system)
        assert pat_index != None

        # Background
        border_width = self._config['border_width']
        painter.setBackground(self._get_final_colour(self._config['bg_colour']))
        painter.eraseRect(QRect(
            border_width, 0,
            self._width - border_width * 2, ColumnCache.PIXMAP_HEIGHT))

        # Start and stop timestamps
        start_px = index * ColumnCache.PIXMAP_HEIGHT
        stop_px = (index + 1) * ColumnCache.PIXMAP_HEIGHT

        visible_tr_start_px = start_px - self._config['tr_height'] + 1
        start_ts = tstamp.Tstamp(0,
                visible_tr_start_px * tstamp.BEAT // self._px_per_beat)
        stop_ts = tstamp.Tstamp(0,
                stop_px * tstamp.BEAT // self._px_per_beat)

        def ts_to_y_offset(ts):
            rems = ts.beats * tstamp.BEAT + ts.rem
            abs_y = rems * self._px_per_beat // tstamp.BEAT
            y_offset = abs_y - start_px
            return y_offset

        # Grid
        sheet_mgr = self._ui_model.get_sheet_manager()
        if sheet_mgr.is_grid_enabled():
            pinsts = utils.get_all_pattern_instances(self._ui_model)
            pinst = pinsts[pat_index]

            grid_start_ts = tstamp.Tstamp(0, start_px * tstamp.BEAT // self._px_per_beat)
            tr_height_ts = utils.get_tstamp_from_px(
                    self._config['tr_height'], self._px_per_beat)
            lines = grid.get_grid_lines(
                    pinst, self._col_num, grid_start_ts, stop_ts, tr_height_ts)

            for line_info in lines:
                line_ts, line_style = line_info
                line_y_offset = ts_to_y_offset(line_ts)

                line_pixmap = self._gl_cache.get_line_pixmap(line_style)
                painter.drawPixmap(QPoint(border_width, line_y_offset), line_pixmap)

        # Trigger rows
        painter.save()
        for ts, images, next_ts in self._tr_cache.iter_rows(start_ts, stop_ts):
            y_offset = ts_to_y_offset(ts)

            tr_height = self._config['tr_height']
            if next_ts != None:
                next_y_offset = ts_to_y_offset(next_ts)
                tr_height = min(max(1, next_y_offset - y_offset), tr_height)

            x_offset = border_width
            for image in images:
                if x_offset >= self._width - border_width * 2:
                    break

                painter.setClipRegion(
                        QRegion(x_offset, y_offset, image.width(), tr_height))
                painter.drawImage(x_offset, y_offset, image)
                x_offset += image.width()
        painter.restore()

        # Borders
        border_light, border_dark = self._get_border_colours()
        if border_width > 1:
            painter.fillRect(
                    QRect(QPoint(0, 0), QSize(border_width, ColumnCache.PIXMAP_HEIGHT)),
                    border_light)
            painter.fillRect(
                    QRect(QPoint(self._width - border_width, 0),
                        QSize(border_width, ColumnCache.PIXMAP_HEIGHT)),
                    border_dark)
        else:
            painter.setPen(border_light)
            painter.drawLine(
                    QPoint(0, 0), QPoint(0, ColumnCache.PIXMAP_HEIGHT))
            painter.setPen(border_dark)
            painter.drawLine(
                    QPoint(self._width - 1, 0),
                    QPoint(self._width - 1, ColumnCache.PIXMAP_HEIGHT))

        # Testing
        """
        painter.setBackground(Qt.black)
        painter.eraseRect(QRect(0, 0, self._width, ColumnCache.PIXMAP_HEIGHT))
        painter.setPen(Qt.white)
        painter.drawRect(0, 0, self._width - 1, ColumnCache.PIXMAP_HEIGHT - 1)
        pixmap_desc = '{}-{}-{}'.format(self._col_num, pat_index, index)
        painter.drawText(QPoint(2, 12), pixmap_desc)
        """

        return pixmap
Пример #19
0
    def paintEvent(self, event):
        start = time.time()

        painter = QPainter(self)
        painter.setBackground(self._config['bg_colour'])
        painter.eraseRect(0, 0, self.width(), self.height())

        painter.translate(QPoint(0, self.height() // 2))

        width_index = count()

        def shift_x():
            cur_width_index = next(width_index)
            painter.translate(QPoint(self._widths[cur_width_index], 0))
            cur_width = self._widths[cur_width_index + 1]
            painter.setClipRect(
                QRectF(0, -self.height() * 0.5, cur_width, self.height()))

        title_y = self.height() * 0.3

        # Get position information
        track_num = -1
        system_num = -1
        row_ts = tstamp.Tstamp()
        pat_num = -1
        inst_num = -1

        playback_mgr = self._ui_model.get_playback_manager()
        if playback_mgr.is_playback_active():
            track_num, system_num, row_ts = playback_mgr.get_playback_position(
            )

            pinst = playback_mgr.get_playback_pattern()
            album = self._ui_model.get_module().get_album()
            if pinst:
                pat_num, inst_num = pinst
            elif album.get_existence():
                song = album.get_song_by_track(track_num)
                if song.get_existence():
                    pinst = song.get_pattern_instance(system_num)
                    pat_num = pinst.get_pattern_num()
                    inst_num = pinst.get_instance_num()
            assert (pat_num == -1) == (inst_num == -1)

        # State icon
        shift_x()
        self._draw_state_icon(painter)

        # Track number
        shift_x()
        shift_x()
        self._draw_str(painter,
                       str(track_num) if track_num >= 0 else '-',
                       self._config['track_digits'], 'num_font')

        painter.setClipping(False)
        painter.drawPixmap(0, title_y, self._titles['track'])

        # System number
        shift_x()
        shift_x()
        self._draw_str(painter,
                       str(system_num) if system_num >= 0 else '-',
                       self._config['system_digits'], 'num_font')

        painter.setClipping(False)
        painter.drawPixmap(2, title_y, self._titles['system'])

        # Pattern instance
        shift_x()
        shift_x()

        # Shift horizontally to align pattern + instance number properly
        pat_shift = 0
        if pat_num >= 0:
            pat_num_width = self._get_num_width(str(pat_num),
                                                self._config['pat_digits'],
                                                'num_font')
            pat_shift = 0.5 * (pat_num_width - self._get_num_width(
                '9', self._config['pat_digits'], 'num_font'))
            if inst_num >= 0:
                inst_num_width = self._get_num_width(
                    str(inst_num), self._config['pat_inst_digits'], 'sub_font')
                inst_def_width = self._get_num_width(
                    '9', self._config['pat_inst_digits'], 'sub_font')
                inst_shift = 0.5 * (inst_def_width - inst_num_width)
                pat_shift += inst_shift
        else:
            inst_def_width = self._get_num_width(
                '9', self._config['pat_inst_digits'], 'sub_font')
            pat_shift = 0.4 * inst_def_width

        painter.save()
        painter.translate(pat_shift, 0)
        painter.setClipRegion(painter.clipRegion().translated(pat_shift, 0))
        self._draw_str(painter,
                       str(pat_num) if pat_num >= 0 else '-',
                       self._config['pat_digits'], 'num_font', Qt.AlignRight)
        painter.restore()

        shift_x()

        if inst_num >= 0:
            painter.save()
            painter.translate(pat_shift, 0)
            painter.setClipRegion(painter.clipRegion().translated(
                pat_shift, 0))
            self._draw_str(painter, str(inst_num),
                           self._config['pat_inst_digits'], 'sub_font',
                           Qt.AlignLeft)
            painter.restore()

        painter.setClipping(False)
        painter.drawPixmap(-19, title_y, self._titles['pattern'])

        # Timestamp
        beats, rem = row_ts
        rem_norm = int(
            float(rem / float(tstamp.BEAT)) *
            (10**self._config['ts_rem_digits'][0]))

        shift_x()
        shift_x()
        self._draw_str(painter, str(beats), self._config['ts_beat_digits'],
                       'num_font', Qt.AlignRight)

        shift_x()
        self._draw_str(painter, '.', [1, 1], 'num_font')

        shift_x()
        self._draw_str(painter, str(rem_norm), self._config['ts_rem_digits'],
                       'rem_font', Qt.AlignLeft)

        painter.setClipping(False)
        painter.drawPixmap(-10, title_y, self._titles['row'])

        end = time.time()
        elapsed = end - start