Exemple #1
0
    def find_parent_scope(block):
        """
        Find parent scope, if the block is not a fold trigger.

        :param block: block from which the research will start
        """
        # if we moved up for more than n lines, just give up otherwise this
        # would take too much time.
        limit = 5000
        counter = 0
        original = block
        if not TextBlockHelper.is_fold_trigger(block):
            # search level of next non blank line
            while block.text().strip() == '' and block.isValid():
                block = block.next()
            ref_lvl = TextBlockHelper.get_fold_lvl(block) - 1
            block = original
            while (block.blockNumber() and counter < limit
                   and (not TextBlockHelper.is_fold_trigger(block)
                        or TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                counter += 1
                block = block.previous()
        if counter < limit:
            return block
        return None
Exemple #2
0
    def find_parent_scope(block):
        """
        Find parent scope, if the block is not a fold trigger.

        :param block: block from which the research will start
        """
        # if we moved up for more than n lines, just give up otherwise this
        # would take too much time.
        limit = 5000
        counter = 0
        original = block
        if not TextBlockHelper.is_fold_trigger(block):
            # search level of next non blank line
            while block.text().strip() == '' and block.isValid():
                block = block.next()
            ref_lvl = TextBlockHelper.get_fold_lvl(block) - 1
            block = original
            while (block.blockNumber() and counter < limit and
                   (not TextBlockHelper.is_fold_trigger(block) or
                    TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                counter += 1
                block = block.previous()
        if counter < limit:
            return block
        return None
Exemple #3
0
    def process_block(self, current_block, previous_block, text):
        """
        Processes a block and setup its folding info.

        This method call ``detect_fold_level`` and handles most of the tricky
        corner cases so that all you have to do is focus on getting the proper
        fold level foreach meaningful block, skipping the blank ones.

        :param current_block: current block to process
        :param previous_block: previous block
        :param text: current block text
        """
        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)
        if text.strip() == '' or self.editor.is_comment(current_block):
            # blank or comment line always have the same level
            # as the previous line
            fold_level = prev_fold_level
        else:
            fold_level = self.detect_fold_level(
                previous_block, current_block)
            if fold_level > self.limit:
                fold_level = self.limit

        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)

        if fold_level > prev_fold_level:
            # apply on previous blank or comment lines
            block = current_block.previous()
            while block.isValid() and (block.text().strip() == ''
                                       or self.editor.is_comment(block)):
                TextBlockHelper.set_fold_lvl(block, fold_level)
                block = block.previous()
            TextBlockHelper.set_fold_trigger(
                block, True)

        # update block fold level
        if text.strip() and not self.editor.is_comment(previous_block):
            TextBlockHelper.set_fold_trigger(
                previous_block, fold_level > prev_fold_level)
        TextBlockHelper.set_fold_lvl(current_block, fold_level)

        # user pressed enter at the beginning of a fold trigger line
        # the previous blank or comment line will keep the trigger state
        # and the new line (which actually contains the trigger) must use
        # the prev state (and prev state must then be reset).
        prev = current_block.previous()  # real prev block (may be blank)
        if (prev and prev.isValid() and
            (prev.text().strip() == '' or self.editor.is_comment(prev)) and
                TextBlockHelper.is_fold_trigger(prev)):
            # prev line has the correct trigger fold state
            TextBlockHelper.set_collapsed(
                current_block, TextBlockHelper.is_collapsed(
                    prev))
            # make empty or comment line not a trigger
            TextBlockHelper.set_fold_trigger(prev, False)
            TextBlockHelper.set_collapsed(prev, False)
Exemple #4
0
    def process_block(self, current_block, previous_block, text):
        """
        Processes a block and setup its folding info.

        This method call ``detect_fold_level`` and handles most of the tricky
        corner cases so that all you have to do is focus on getting the proper
        fold level foreach meaningful block, skipping the blank ones.

        :param current_block: current block to process
        :param previous_block: previous block
        :param text: current block text
        """
        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)
        if text.strip() == '' or self.editor.is_comment(current_block):
            # blank or comment line always have the same level
            # as the previous line
            fold_level = prev_fold_level
        else:
            fold_level = self.detect_fold_level(previous_block, current_block)
            if fold_level > self.limit:
                fold_level = self.limit

        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)

        if fold_level > prev_fold_level:
            # apply on previous blank or comment lines
            block = current_block.previous()
            while block.isValid() and (block.text().strip() == ''
                                       or self.editor.is_comment(block)):
                TextBlockHelper.set_fold_lvl(block, fold_level)
                block = block.previous()
            TextBlockHelper.set_fold_trigger(block, True)

        # update block fold level
        if text.strip() and not self.editor.is_comment(previous_block):
            TextBlockHelper.set_fold_trigger(previous_block,
                                             fold_level > prev_fold_level)
        TextBlockHelper.set_fold_lvl(current_block, fold_level)

        # user pressed enter at the beginning of a fold trigger line
        # the previous blank or comment line will keep the trigger state
        # and the new line (which actually contains the trigger) must use
        # the prev state (and prev state must then be reset).
        prev = current_block.previous()  # real prev block (may be blank)
        if (prev and prev.isValid()
                and (prev.text().strip() == '' or self.editor.is_comment(prev))
                and TextBlockHelper.is_fold_trigger(prev)):
            # prev line has the correct trigger fold state
            TextBlockHelper.set_collapsed(current_block,
                                          TextBlockHelper.is_collapsed(prev))
            # make empty or comment line not a trigger
            TextBlockHelper.set_fold_trigger(prev, False)
            TextBlockHelper.set_collapsed(prev, False)
Exemple #5
0
 def find_parent_scope(block):
     """Find parent scope, if the block is not a fold trigger."""
     original = block
     if not TextBlockHelper.is_fold_trigger(block):
         # search level of next non blank line
         while block.text().strip() == '' and block.isValid():
             block = block.next()
         ref_lvl = TextBlockHelper.get_fold_lvl(block) - 1
         block = original
         while (block.blockNumber() and
                (not TextBlockHelper.is_fold_trigger(block) or
                 TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
             block = block.previous()
     return block
Exemple #6
0
 def find_parent_scope(block):
     """Find parent scope, if the block is not a fold trigger."""
     original = block
     if not TextBlockHelper.is_fold_trigger(block):
         # search level of next non blank line
         while block.text().strip() == '' and block.isValid():
             block = block.next()
         ref_lvl = TextBlockHelper.get_fold_lvl(block) - 1
         block = original
         while (block.blockNumber()
                and (not TextBlockHelper.is_fold_trigger(block)
                     or TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
             block = block.previous()
     return block
Exemple #7
0
 def detect_fold_level(self, prev_block, block):
     if prev_block:
         prev_text = prev_block.text().strip()
     else:
         prev_text = ''
     text = block.text().strip()
     if text in self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if prev_text.endswith(self.open_chars) and prev_text not in \
             self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if self.close_chars in prev_text:
         return TextBlockHelper.get_fold_lvl(prev_block) - 1
     return TextBlockHelper.get_fold_lvl(prev_block)
Exemple #8
0
 def detect_fold_level(self, prev_block, block):
     if prev_block:
         prev_text = prev_block.text().strip()
     else:
         prev_text = ''
     text = block.text().strip()
     if text in self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if prev_text.endswith(self.open_chars) and prev_text not in \
             self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if self.close_chars in prev_text:
         return TextBlockHelper.get_fold_lvl(prev_block) - 1
     return TextBlockHelper.get_fold_lvl(prev_block)
Exemple #9
0
    def get_range(self, ignore_blank_lines=True):
        """
        Gets the fold region range (start and end line).

        .. note:: Start line do no encompass the trigger line.

        :param ignore_blank_lines: True to ignore blank lines at the end of the
            scope (the method will rewind to find that last meaningful block
            that is part of the fold scope).
        :returns: tuple(int, int)
        """
        ref_lvl = self.trigger_level
        first_line = self._trigger.blockNumber()
        block = self._trigger.next()
        last_line = block.blockNumber()
        lvl = self.scope_level
        if ref_lvl == lvl:  # for zone set programmatically such as imports
                            # in pyqode.python
            ref_lvl -= 1
        while (block.isValid() and
                TextBlockHelper.get_fold_lvl(block) > ref_lvl):
            last_line = block.blockNumber()
            block = block.next()

        if ignore_blank_lines and last_line:
            block = block.document().findBlockByNumber(last_line)
            while block.blockNumber() and block.text().strip() == '':
                block = block.previous()
                last_line = block.blockNumber()
        return first_line, last_line
Exemple #10
0
    def get_range(self, ignore_blank_lines=True):
        """
        Gets the fold region range (start and end line).

        .. note:: Start line do no encompass the trigger line.

        :param ignore_blank_lines: True to ignore blank lines at the end of the
            scope (the method will rewind to find that last meaningful block
            that is part of the fold scope).
        :returns: tuple(int, int)
        """
        ref_lvl = self.trigger_level
        first_line = self._trigger.blockNumber()
        block = self._trigger.next()
        last_line = block.blockNumber()
        lvl = self.scope_level
        if ref_lvl == lvl:  # for zone set programmatically such as imports
            # in pyqode.python
            ref_lvl -= 1
        while (block.isValid()
               and TextBlockHelper.get_fold_lvl(block) > ref_lvl):
            last_line = block.blockNumber()
            block = block.next()

        if ignore_blank_lines and last_line:
            block = block.document().findBlockByNumber(last_line)
            while block.blockNumber() and block.text().strip() == '':
                block = block.previous()
                last_line = block.blockNumber()
        return first_line, last_line
Exemple #11
0
 def collapse_all(self):
     """
     Collapses all triggers and makes all blocks with fold level > 0
     invisible.
     """
     self._clear_block_deco()
     block = self.editor.document().firstBlock()
     last = self.editor.document().lastBlock()
     while block.isValid():
         lvl = TextBlockHelper.get_fold_lvl(block)
         trigger = TextBlockHelper.is_fold_trigger(block)
         if trigger:
             if lvl == 0:
                 self._show_previous_blank_lines(block)
             TextBlockHelper.set_collapsed(block, True)
         block.setVisible(lvl == 0)
         if block == last and block.text().strip() == '':
             block.setVisible(True)
             self._show_previous_blank_lines(block)
         block = block.next()
     self._refresh_editor_and_scrollbars()
     tc = self.editor.textCursor()
     tc.movePosition(tc.Start)
     self.editor.setTextCursor(tc)
     self.collapse_all_triggered.emit()
Exemple #12
0
 def collapse_all(self):
     """
     Collapses all triggers and makes all blocks with fold level > 0
     invisible.
     """
     self._clear_block_deco()
     block = self.editor.document().firstBlock()
     last = self.editor.document().lastBlock()
     while block.isValid():
         lvl = TextBlockHelper.get_fold_lvl(block)
         trigger = TextBlockHelper.is_fold_trigger(block)
         if trigger:
             if lvl == 0:
                 self._show_previous_blank_lines(block)
             TextBlockHelper.set_collapsed(block, True)
         block.setVisible(lvl == 0)
         if block == last and block.text().strip() == '':
             block.setVisible(True)
             self._show_previous_blank_lines(block)
         block = block.next()
     self._refresh_editor_and_scrollbars()
     tc = self.editor.textCursor()
     tc.movePosition(tc.Start)
     self.editor.setTextCursor(tc)
     self.collapse_all_triggered.emit()
Exemple #13
0
    def scope_level(self):
        """
        Returns the fold level of the first block of the foldable scope (
        just after the trigger).

        :return:
        """
        return TextBlockHelper.get_fold_lvl(self._trigger.next())
Exemple #14
0
    def scope_level(self):
        """
        Returns the fold level of the first block of the foldable scope (
        just after the trigger).

        :return:
        """
        return TextBlockHelper.get_fold_lvl(self._trigger.next())
Exemple #15
0
    def parent(self):
        """
        Return the parent scope.

        :return: FoldScope or None
        """
        if TextBlockHelper.get_fold_lvl(self._trigger) > 0 and \
                self._trigger.blockNumber():
            block = self._trigger.previous()
            ref_lvl = self.trigger_level - 1
            while (block.blockNumber()
                   and (not TextBlockHelper.is_fold_trigger(block)
                        or TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                block = block.previous()
            try:
                return FoldScope(block)
            except ValueError:
                return None
        return None
Exemple #16
0
    def parent(self):
        """
        Return the parent scope.

        :return: FoldScope or None
        """
        if TextBlockHelper.get_fold_lvl(self._trigger) > 0 and \
                self._trigger.blockNumber():
            block = self._trigger.previous()
            ref_lvl = self.trigger_level - 1
            while (block.blockNumber() and
                    (not TextBlockHelper.is_fold_trigger(block) or
                     TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                block = block.previous()
            try:
                return FoldScope(block)
            except ValueError:
                return None
        return None
Exemple #17
0
 def child_regions(self):
     """This generator generates the list of direct child regions."""
     start, end = self.get_range()
     block = self._trigger.next()
     ref_lvl = self.scope_level
     while block.blockNumber() <= end and block.isValid():
         lvl = TextBlockHelper.get_fold_lvl(block)
         trigger = TextBlockHelper.is_fold_trigger(block)
         if lvl == ref_lvl and trigger:
             yield FoldScope(block)
         block = block.next()
Exemple #18
0
 def child_regions(self):
     """This generator generates the list of direct child regions."""
     start, end = self.get_range()
     block = self._trigger.next()
     ref_lvl = self.scope_level
     while block.blockNumber() <= end and block.isValid():
         lvl = TextBlockHelper.get_fold_lvl(block)
         trigger = TextBlockHelper.is_fold_trigger(block)
         if lvl == ref_lvl and trigger:
             yield FoldScope(block)
         block = block.next()
Exemple #19
0
    def paintEvent(self, event):
        """Override Qt method."""
        painter = QPainter(self)

        color = QColor(self.color)
        color.setAlphaF(.5)
        painter.setPen(color)

        for top, line_number, block in self.editor.visible_blocks:
            bottom = top + int(self.editor.blockBoundingRect(block).height())

            indentation = TextBlockHelper.get_fold_lvl(block)

            for i in range(1, indentation):
                x = self.editor.fontMetrics().width(i * self.i_width * '9')
                painter.drawLine(x, top, x, bottom)
Exemple #20
0
    def paintEvent(self, event):
        """Override Qt method."""
        painter = QPainter(self)

        color = QColor(self.color)
        color.setAlphaF(.5)
        painter.setPen(color)

        for top, line_number, block in self.editor.visible_blocks:
            bottom = top + int(self.editor.blockBoundingRect(block).height())

            indentation = TextBlockHelper.get_fold_lvl(block)

            for i in range(1, indentation):
                x = self.editor.fontMetrics().width(i * self.i_width * '9')
                painter.drawLine(x, top, x, bottom)
Exemple #21
0
 def trigger_level(self):
     """
     Returns the fold level of the block trigger.
     :return:
     """
     return TextBlockHelper.get_fold_lvl(self._trigger)
Exemple #22
0
 def trigger_level(self):
     """
     Returns the fold level of the block trigger.
     :return:
     """
     return TextBlockHelper.get_fold_lvl(self._trigger)