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() == '': # blank 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 if fold_level > prev_fold_level: # apply on previous blank lines block = current_block.previous() while block.isValid() and block.text().strip() == '': TextBlockHelper.set_fold_lvl(block, fold_level) block = block.previous() TextBlockHelper.set_fold_trigger(block, True) delta_abs = abs(fold_level - prev_fold_level) if delta_abs > 1: if fold_level > prev_fold_level: # try to fix inconsistent fold level _logger().debug( '(l%d) inconsistent fold level, difference between ' 'consecutive blocks cannot be greater than 1 (%d).', current_block.blockNumber() + 1, delta_abs) fold_level = prev_fold_level + 1 # update block fold level if text.strip(): 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 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() == '' and TextBlockHelper.is_fold_trigger(prev)): # prev line has the correct trigger fold state TextBlockHelper.set_fold_trigger_state( current_block, TextBlockHelper.get_fold_trigger_state(prev)) # make empty line not a trigger TextBlockHelper.set_fold_trigger(prev, False) TextBlockHelper.set_fold_trigger_state(prev, False)
def fold(self): """ Folds the region. """ start, end = self.get_range() TextBlockHelper.set_fold_trigger_state(self._trigger, True) block = self._trigger.next() while block.blockNumber() <= end and block.isValid(): block.setVisible(False) block = block.next()
def unfold(self): """ Unfolds the region. """ # set all direct child blocks which are not triggers to be visible self._trigger.setVisible(True) TextBlockHelper.set_fold_trigger_state(self._trigger, False) for block in self.blocks(ignore_blank_lines=False): block.setVisible(True) for region in self.child_regions(): if not region.collapsed: region.unfold() else: # leave it closed but open the last blank lines and the # trigger line start, bstart = region.get_range(ignore_blank_lines=True) _, bend = region.get_range(ignore_blank_lines=False) block = self._trigger.document().findBlockByNumber(start) block.setVisible(True) block = self._trigger.document().findBlockByNumber(bend) while block.blockNumber() > bstart: block.setVisible(True) block = block.previous()
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() == '': # blank 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 if fold_level > prev_fold_level: # apply on previous blank lines block = current_block.previous() while block.isValid() and block.text().strip() == '': TextBlockHelper.set_fold_lvl(block, fold_level) block = block.previous() TextBlockHelper.set_fold_trigger( block, True) delta_abs = abs(fold_level - prev_fold_level) if delta_abs > 1: if fold_level > prev_fold_level: # try to fix inconsistent fold level _logger().debug( '(l%d) inconsistent fold level, difference between ' 'consecutive blocks cannot be greater than 1 (%d).', current_block.blockNumber() + 1, delta_abs) fold_level = prev_fold_level + 1 # update block fold level if text.strip(): 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 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() == '' and TextBlockHelper.is_fold_trigger(prev)): # prev line has the correct trigger fold state TextBlockHelper.set_fold_trigger_state( current_block, TextBlockHelper.get_fold_trigger_state( prev)) # make empty line not a trigger TextBlockHelper.set_fold_trigger(prev, False) TextBlockHelper.set_fold_trigger_state(prev, False)