示例#1
0
 def draw_line_hexagon(self, 
                       position, 
                       line_width, 
                       line_color,
                       paint_enabled=[True,True,True,True,True,True],
                       shadow=False):
     qpainter = self.painter
     
     if line_width == 0:
         return
     
     pen = data.QPen(data.Qt.SolidLine)
     pen.setCapStyle(data.Qt.RoundCap)
     pen.setJoinStyle(data.Qt.RoundJoin)
     pen.setWidth(line_width)
     pen.setColor(line_color)
     qpainter.setPen(pen)
     hex_points = list(
         HexBuilder.generate_hexagon_points(self.edge_length, position)
     )
     x_correction = self.edge_length / 2
     y_correction = self.edge_length / (2 * math.tan(math.radians(30)))
     hex_points = [(x-x_correction, y-y_correction) for x, y in hex_points]
     hex_lines = []
     
     for i in range(len(hex_points)):
         if paint_enabled[i] == False:
             continue
         n = i + 1
         if n > (len(hex_points)-1):
             n = 0
         hex_lines.append(
             data.QLine(
                 data.QPoint(*hex_points[i]), 
                 data.QPoint(*hex_points[n])
             )
         )
     if hex_lines:
         if shadow == True:
             shadow_0_color = data.QColor(line_color)
             shadow_0_color.setAlpha(64)
             shadow_1_color = data.QColor(line_color)
             shadow_1_color.setAlpha(128)
             
             pen.setWidth(line_width*2.0)
             pen.setColor(shadow_0_color)
             qpainter.setPen(pen)
             qpainter.drawLines(*hex_lines)
             pen.setWidth(line_width*1.5)
             pen.setColor(shadow_1_color)
             qpainter.setPen(pen)
             qpainter.drawLines(*hex_lines)
             pen.setWidth(line_width)
             pen.setColor(line_color)
             qpainter.setPen(pen)
             qpainter.drawLines(*hex_lines)
         else:
             qpainter.drawLines(*hex_lines)
示例#2
0
    def draw_full_hexagon_with_shadow(self, position, fill_color, line_width,
                                      line_color):
        qpainter = self.painter

        self.draw_filled_hexagon(position, fill_color)
        shadow_0_color = data.QColor(line_color)
        shadow_0_color.setAlpha(64)
        shadow_1_color = data.QColor(line_color)
        shadow_1_color.setAlpha(128)
        self.draw_line_hexagon(position, line_width * 2.0, shadow_0_color)
        self.draw_line_hexagon(position, line_width * 1.5, shadow_1_color)
        self.draw_line_hexagon(position, line_width, line_color)
示例#3
0
文件: awk.py 项目: Mr-ZBin/ExCo
 def set_theme(self, theme):
     for style in self.styles:
         # Papers
         self.setPaper(data.QColor(theme.Paper.AWK.Default),
                       self.styles[style])
         # Fonts
         lexers.set_font(self, style, getattr(theme.Font.AWK, style))
示例#4
0
    def draw_filled_hexagon(self, position, fill_color, number=None):
        qpainter = self.painter

        pen = data.QPen(data.Qt.SolidLine)
        pen.setColor(fill_color)
        brush = data.QBrush(data.Qt.SolidPattern)
        brush.setColor(fill_color)
        qpainter.setBrush(brush)
        qpainter.setPen(pen)
        hex_points = list(
            HexBuilder.generate_hexagon_points(self.edge_length, position))
        x_correction = self.edge_length / 2
        y_correction = self.edge_length / (2 * math.tan(math.radians(30)))
        hex_points = [(x - x_correction, y - y_correction)
                      for x, y in hex_points]
        hex_qpoints = [data.QPoint(*x) for x in hex_points]
        qpainter.drawPolygon(*hex_qpoints)

        if (self.SHOW_FIELD_NUMBERS == True) and (number != None):
            font = data.QFont('Courier', 8)
            font.setBold(True)
            qpainter.setFont(font)
            pen = data.QPen(data.Qt.SolidLine)
            pen.setColor(data.QColor(0, 0, 0))
            qpainter.setPen(pen)

            font_metric = data.QFontMetrics(font)
            x = position[0] - font_metric.width(str(number)) / 2
            y = position[1] + font_metric.height() / 4

            qpainter.drawText(data.QPoint(x, y), str(number))
示例#5
0
文件: nim.py 项目: Mr-ZBin/ExCo
 def set_theme(self, theme):
     for style in self.styles.keys():
         # Papers
         self.setPaper(data.QColor(theme.Paper.Nim.Default),
                       self.styles[style])
         # Fonts
         set_font(self, style, getattr(theme.Font.Nim, style))
示例#6
0
 def set_theme(self, theme):
     for style in self.styles:
         # Papers
         paper = data.QColor(getattr(theme.Paper.Python, style))
         self.setPaper(paper, self.styles[style])
         # Fonts
         lexers.set_font(self, style, getattr(theme.Font.Python, style))
示例#7
0
def set_font(lexer, style_name, style_options):
    font, color, size, bold = style_options
    lexer.setColor(data.QColor(color), lexer.styles[style_name])
    weight = data.QFont.Normal
    if bold == 1 or bold == True:
        weight = data.QFont.Bold
    elif bold == 2:
        weight = data.QFont.Black
    lexer.setFont(data.QFont(font, size, weight=weight),
                  lexer.styles[style_name])
示例#8
0
 def init_editor(self, editor):
     """Initialize all of the PlainEditor settings for difference displaying"""
     editor.setLexer(None)
     editor.setUtf8(True)
     editor.setIndentationsUseTabs(False)
     editor.setFont(self.DEFAULT_FONT)
     editor.setBraceMatching(data.QsciScintilla.SloppyBraceMatch)
     editor.setMatchedBraceBackgroundColor(data.QColor(255, 153, 0))
     editor.setAcceptDrops(False)
     editor.setEolMode(settings.Editor.end_of_line_mode)
     editor.setReadOnly(True)
     editor.savable = data.CanSave.NO
示例#9
0
 def __init__(self, 
              painter, 
              first_position, 
              edge_length, 
              scale=1.0,
              fill_color=data.QColor(255,255,255),
              line_width=1,
              line_color=data.QColor(255,255,255),):
     self.set_first_position(first_position)
     self.painter = painter
     self.scale = scale
     self.edge_length = scale * edge_length
     
     self.horizontal_step, self.vertical_step, self.steps = GridGenerator.init_steps(
         self.edge_length, self.scale
     )
     
     self.fill_color = fill_color
     self.line_width = line_width
     self.line_color = line_color
     
     self.stored_lines = []
示例#10
0
def set_font(lexer, style_name, style_options):
    font, color, size, bold = style_options
    try:
        style_index = lexer.styles[style_name]["index"]
    except:
        style_index = lexer.styles[style_name]
    lexer.setColor(
        data.QColor(color),
        style_index
    )
    weight = data.QFont.Normal
    if bold == 1 or bold == True:
        weight = data.QFont.Bold
    elif bold == 2:
        weight = data.QFont.Black
    lexer.setFont(
        data.QFont(font, size, weight=weight), 
        style_index
    )
示例#11
0
 def create_base_image():
     hex_image = data.QImage(
         functions.create_size(width, height),
         data.QImage.Format_ARGB32_Premultiplied)
     hex_image.fill(data.Qt.transparent)
     qpainter = data.QPainter(hex_image)
     qpainter.setRenderHints(data.QPainter.Antialiasing
                             | data.QPainter.TextAntialiasing
                             | data.QPainter.SmoothPixmapTransform)
     hb = components.HexBuilder(
         qpainter,
         (width / 2, height / 2),
         self.DEFAULT_SIZE,
         self.scale_factor,
         fill_color=data.theme.Settings_Hex_Background,
         line_width=2,
         line_color=data.QColor(64, 64, 64),
     )
     hb.create_grid(False)
     qpainter.end()
     return data.QPixmap.fromImage(hex_image)
示例#12
0
文件: dialogs.py 项目: Mr-ZBin/ExCo
        def draw(self, opacity):
            image = data.QImage(self.pixmap.size(),
                                data.QImage.Format_ARGB32_Premultiplied)
            image.fill(data.Qt.transparent)
            painter = data.QPainter(image)
            painter.setOpacity(opacity)
            painter.drawPixmap(0, 0, self.pixmap)

            if opacity < 0.5:
                painter.setPen(data.theme.Font.Default)
            else:
                painter.setPen(data.QColor(255, 255, 255))
            painter.setFont(
                data.QFont('Segoe UI', int(16 * self.scale), data.QFont.Bold))
            painter.setOpacity(1.0)
            painter.drawText(self.pixmap.rect(), data.Qt.AlignCenter,
                             self.text)
            painter.end()
            # Display the manipulated image
            self.setPixmap(data.QPixmap.fromImage(image))
            # Set the button mask, which sets the button area to the shape of
            # the button image instead of a rectangle
            self.setMask(self.pixmap.mask())
示例#13
0
 def create_color_image(color):
     hex_image = data.QImage(
         data.QSize(width, height),
         data.QImage.Format_ARGB32_Premultiplied
     )
     hex_image.fill(data.Qt.transparent)
     qpainter = data.QPainter(hex_image)
     qpainter.setRenderHints(
         data.QPainter.Antialiasing | 
         data.QPainter.TextAntialiasing | 
         data.QPainter.SmoothPixmapTransform
     )
     hb = components.HexBuilder(
         qpainter, 
         (width/2, height/2), 
         self.DEFAULT_SIZE, 
         self.scale_factor, 
         fill_color=color,
         line_width=0,
         line_color=data.QColor(0,0,0),
     )
     hb.create_grid(False)
     qpainter.end()
     return data.QPixmap.fromImage(hex_image)
示例#14
0
class TextDiffer(data.QWidget):
    """A widget that holds two PlainEditors for displaying text difference"""
    #Class variables
    _parent = None
    main_form = None
    name = ""
    savable = data.CanSave.NO
    current_icon = None
    icon_manipulator = None
    focused_editor = None
    text_1 = None
    text_2 = None
    text_1_name = None
    text_2_name = None
    #Class constants
    DEFAULT_FONT = data.QFont(data.current_font_name, data.current_font_size)
    MARGIN_STYLE = data.QsciScintilla.STYLE_LINENUMBER
    INDICATOR_UNIQUE_1 = 1
    Indicator_Unique_1_Color = data.QColor(0x72, 0x9f, 0xcf, 80)
    INDICATOR_UNIQUE_2 = 2
    Indicator_Unique_2_Color = data.QColor(0xad, 0x7f, 0xa8, 80)
    INDICATOR_SIMILAR = 3
    Indicator_Similar_Color = data.QColor(0x8a, 0xe2, 0x34, 80)
    GET_X_OFFSET = data.QsciScintillaBase.SCI_GETXOFFSET
    SET_X_OFFSET = data.QsciScintillaBase.SCI_SETXOFFSET
    UPDATE_H_SCROLL = data.QsciScintillaBase.SC_UPDATE_H_SCROLL
    UPDATE_V_SCROLL = data.QsciScintillaBase.SC_UPDATE_V_SCROLL
    #Diff icons
    icon_unique_1 = None
    icon_unique_2 = None
    icon_similar = None
    #Marker references
    marker_unique_1 = None
    marker_unique_2 = None
    marker_unique_symbol_1 = None
    marker_unique_symbol_2 = None
    marker_similar_1 = None
    marker_similar_2 = None
    marker_similar_symbol_1 = None
    marker_similar_symbol_2 = None
    #Child widgets
    splitter = None
    editor_1 = None
    editor_2 = None
    layout = None

    def clean_up(self):
        self.editor_1.mousePressEvent = None
        self.editor_1.wheelEvent = None
        self.editor_2.mousePressEvent = None
        self.editor_2.wheelEvent = None
        self.editor_1.actual_parent = None
        self.editor_2.actual_parent = None
        self.editor_1.clean_up()
        self.editor_2.clean_up()
        self.editor_1 = None
        self.editor_2 = None
        self.focused_editor = None
        self.splitter.setParent(None)
        self.splitter = None
        self.layout = None
        self._parent = None
        self.main_form = None
        self.icon_manipulator = None
        # Clean up self
        self.setParent(None)
        self.deleteLater()
        """
        The actual clean up will occur when the next garbage collection
        cycle is executed, probably because of the nested functions and 
        the focus decorator.
        """

    def __init__(self,
                 parent,
                 main_form,
                 text_1=None,
                 text_2=None,
                 text_1_name="",
                 text_2_name=""):
        """Initialization"""
        # Initialize the superclass
        super().__init__(parent)
        # Initialize components
        self.icon_manipulator = components.IconManipulator(self, parent)
        # Initialize colors according to theme
        self.Indicator_Unique_1_Color = data.theme.TextDifferColors.Indicator_Unique_1_Color
        self.Indicator_Unique_2_Color = data.theme.TextDifferColors.Indicator_Unique_2_Color
        self.Indicator_Similar_Color = data.theme.TextDifferColors.Indicator_Similar_Color
        # Store the reference to the parent
        self._parent = parent
        # Store the reference to the main form
        self.main_form = main_form
        # Set the differ icon
        self.current_icon = functions.create_icon(
            'tango_icons/compare-text.png')
        #Set the name of the differ widget
        if text_1_name != None and text_2_name != None:
            self.name = "Text difference: {:s} / {:s}".format(
                text_1_name, text_2_name)
            self.text_1_name = text_1_name
            self.text_2_name = text_2_name
        else:
            self.name = "Text difference"
            self.text_1_name = "TEXT 1"
            self.text_2_name = "TEXT 2"
        # Initialize diff icons
        self.icon_unique_1 = functions.create_icon(
            "tango_icons/diff-unique-1.png")
        self.icon_unique_2 = functions.create_icon(
            "tango_icons/diff-unique-2.png")
        self.icon_similar = functions.create_icon(
            "tango_icons/diff-similar.png")
        # Create the horizontal splitter and two editor widgets
        self.splitter = data.QSplitter(data.Qt.Horizontal, self)
        self.editor_1 = CustomEditor(self, main_form)
        self.init_editor(self.editor_1)
        self.editor_2 = CustomEditor(self, main_form)
        self.init_editor(self.editor_2)
        self.editor_1.choose_lexer("text")
        self.editor_2.choose_lexer("text")
        self.splitter.addWidget(self.editor_1)
        self.splitter.addWidget(self.editor_2)
        self.layout = data.QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.addWidget(self.splitter)
        # Set the layout
        self.setLayout(self.layout)
        # Connect the necessary signals
        self.editor_1.SCN_UPDATEUI.connect(self._scn_updateui_1)
        self.editor_2.SCN_UPDATEUI.connect(self._scn_updateui_2)
        self.editor_1.cursorPositionChanged.connect(self._cursor_change_1)
        self.editor_2.cursorPositionChanged.connect(self._cursor_change_2)
        # Overwrite the CustomEditor parent widgets to point to the TextDiffers' PARENT
        self.editor_1._parent = self._parent
        self.editor_2._parent = self._parent
        # Add a new attribute to the CustomEditor that will hold the TextDiffer reference
        self.editor_1.actual_parent = self
        self.editor_2.actual_parent = self
        # Set the embedded flag
        self.editor_1.embedded = True
        self.editor_2.embedded = True

        # Add decorators to each editors mouse clicks and mouse wheel scrolls
        def focus_decorator(function_to_decorate, focused_editor):
            def decorated_function(*args, **kwargs):
                self.focused_editor = focused_editor
                function_to_decorate(*args, **kwargs)

            return decorated_function

        self.editor_1.mousePressEvent = focus_decorator(
            self.editor_1.mousePressEvent, self.editor_1)
        self.editor_1.wheelEvent = focus_decorator(self.editor_1.wheelEvent,
                                                   self.editor_1)
        self.editor_2.mousePressEvent = focus_decorator(
            self.editor_2.mousePressEvent, self.editor_2)
        self.editor_2.wheelEvent = focus_decorator(self.editor_2.wheelEvent,
                                                   self.editor_2)
        # Add corner buttons
        self.add_corner_buttons()
        # Focus the first editor on initialization
        self.focused_editor = self.editor_1
        self.focused_editor.setFocus()
        # Initialize markers
        self.init_markers()
        # Set the theme
        self.set_theme(data.theme)
        # Set editor functions that have to be propagated from the TextDiffer
        # to the child editor
        self._init_editor_functions()
        # Check the text validity
        if text_1 == None or text_2 == None:
            #One of the texts is unspecified
            return
        # Create the diff
        self.compare(text_1, text_2)

    def _scn_updateui_1(self, sc_update):
        """Function connected to the SCN_UPDATEUI signal for scroll detection"""
        if self.focused_editor == self.editor_1:
            #Scroll the opposite editor
            if sc_update == self.UPDATE_H_SCROLL:
                current_x_offset = self.editor_1.SendScintilla(
                    self.GET_X_OFFSET)
                self.editor_2.SendScintilla(self.SET_X_OFFSET,
                                            current_x_offset)
            elif sc_update == self.UPDATE_V_SCROLL:
                current_top_line = self.editor_1.firstVisibleLine()
                self.editor_2.setFirstVisibleLine(current_top_line)

    def _scn_updateui_2(self, sc_update):
        """Function connected to the SCN_UPDATEUI signal for scroll detection"""
        if self.focused_editor == self.editor_2:
            #Scroll the opposite editor
            if sc_update == self.UPDATE_H_SCROLL:
                current_x_offset = self.editor_2.SendScintilla(
                    self.GET_X_OFFSET)
                self.editor_1.SendScintilla(self.SET_X_OFFSET,
                                            current_x_offset)
            elif sc_update == self.UPDATE_V_SCROLL:
                current_top_line = self.editor_2.firstVisibleLine()
                self.editor_1.setFirstVisibleLine(current_top_line)

    def _cursor_change_1(self, line, index):
        """
        Function connected to the cursorPositionChanged signal for
        cursor position change detection
        """
        if self.focused_editor == self.editor_1:
            #Update the cursor position on the opposite editor
            cursor_line, cursor_index = self.editor_1.getCursorPosition()
            #Check if the opposite editor line is long enough
            if self.editor_2.lineLength(cursor_line) > cursor_index:
                self.editor_2.setCursorPosition(cursor_line, cursor_index)
            else:
                self.editor_2.setCursorPosition(cursor_line, 0)
            #Update the first visible line, so that the views in both differs match
            current_top_line = self.editor_1.firstVisibleLine()
            self.editor_2.setFirstVisibleLine(current_top_line)

    def _cursor_change_2(self, line, index):
        """
        Function connected to the cursorPositionChanged signal for
        cursor position change detection
        """
        if self.focused_editor == self.editor_2:
            #Update the cursor position on the opposite editor
            cursor_line, cursor_index = self.editor_2.getCursorPosition()
            #Check if the opposite editor line is long enough
            if self.editor_1.lineLength(cursor_line) > cursor_index:
                self.editor_1.setCursorPosition(cursor_line, cursor_index)
            else:
                self.editor_1.setCursorPosition(cursor_line, 0)
            #Update the first visible line, so that the views in both differs match
            current_top_line = self.editor_2.firstVisibleLine()
            self.editor_1.setFirstVisibleLine(current_top_line)

    def _update_margins(self):
        """Update the text margin width"""
        self.editor_1.setMarginWidth(0, "0" * len(str(self.editor_1.lines())))
        self.editor_2.setMarginWidth(0, "0" * len(str(self.editor_2.lines())))

    def _signal_editor_cursor_change(self,
                                     cursor_line=None,
                                     cursor_column=None):
        """Signal that fires when cursor position changes in one of the editors"""
        self.main_form.display.update_cursor_position(cursor_line,
                                                      cursor_column)

    def _init_editor_functions(self):
        """
        Initialize the editor functions that are called on the TextDiffer widget,
        but need to be executed on one of the editors
        """

        #Find text function propagated to the focused editor
        def enabled_function(*args, **kwargs):
            #Get the function
            function = getattr(self.focused_editor, args[0])
            #Call the function˘, leaving out the "function name" argument
            function(*args[1:], **kwargs)

        #Unimplemented functions
        def uniplemented_function(*args, **kwargs):
            self.main_form.display.repl_display_message(
                "Function '{:s}' is not implemented by the TextDiffer!".format(
                    args[0]),
                message_type=data.MessageType.ERROR)

        all_editor_functions = inspect.getmembers(CustomEditor,
                                                  predicate=inspect.isfunction)
        skip_functions = [
            "set_theme",
            "clean_up",
        ]
        enabled_functions = [
            "find_text",
        ]
        disabled_functions = [
            "__init__",
            "__setattr__",
            "_filter_keypress",
            "_filter_keyrelease",
            "_init_special_functions",
            "_set_indicator",
            "find_text",
            "keyPressEvent",
            "keyReleaseEvent",
            "mousePressEvent",
            "setFocus",
            "wheelEvent",
        ]
        #Check methods
        for function in all_editor_functions:
            if function[0] in skip_functions:
                #Use the TextDiffer implementation of this function
                continue
            if function[0] in enabled_functions:
                #Find text is enabled
                setattr(self, function[0],
                        functools.partial(enabled_function, function[0]))
            elif function[0] in disabled_functions:
                #Disabled functions should be skipped, they are probably already
                #implemented by the TextDiffer
                continue
            else:
                #Unimplemented functions should display an error message
                setattr(self, function[0],
                        functools.partial(uniplemented_function, function[0]))

    def mousePressEvent(self, event):
        """Overloaded mouse click event"""
        #Execute the superclass mouse click event
        super().mousePressEvent(event)
        #Set focus to the clicked editor
        self.setFocus()
        #Set the last focused widget to the parent basic widget
        self.main_form.last_focused_widget = self._parent
        data.print_log("Stored \"{:s}\" as last focused widget".format(
            self._parent.name))
        #Hide the function wheel if it is shown
        self.main_form.view.hide_all_overlay_widgets()
        # Reset the click&drag context menu action
        components.ActionFilter.clear_action()

    def setFocus(self):
        """Overridden focus event"""
        #Execute the superclass focus function
        super().setFocus()
        #Check indication
        self.main_form.view.indication_check()
        #Focus the last focused editor
        self.focused_editor.setFocus()

    def init_margin(self, editor, marker_unique, marker_unique_symbol,
                    marker_similar, marker_similar_symbol):
        """Initialize margin for coloring lines showing diff symbols"""
        editor.setMarginWidth(0, "0")
        #Setting the margin width to 0 makes the marker colour the entire line
        #to the marker background color
        editor.setMarginWidth(1, "00")
        editor.setMarginWidth(2, 0)
        editor.setMarginType(0, data.QsciScintilla.TextMargin)
        editor.setMarginType(1, data.QsciScintilla.SymbolMargin)
        editor.setMarginType(2, data.QsciScintilla.SymbolMargin)
        #I DON'T KNOW THE ENTIRE LOGIC BEHIND MARKERS AND MARGINS! If you set
        #something wrong in the margin mask, the markers on a different margin don't appear!
        #http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINMASKN
        editor.setMarginMarkerMask(1, ~data.QsciScintillaBase.SC_MASK_FOLDERS)
        editor.setMarginMarkerMask(2, 0x0)

    def init_markers(self):
        """Initialize all markers for showing diff symbols"""
        #Set the images
        image_scale_size = functions.create_size(16, 16)
        image_unique_1 = functions.create_pixmap(
            'tango_icons/diff-unique-1.png')
        image_unique_2 = functions.create_pixmap(
            'tango_icons/diff-unique-2.png')
        image_similar = functions.create_pixmap('tango_icons/diff-similar.png')
        #Scale the images to a smaller size
        image_unique_1 = image_unique_1.scaled(image_scale_size)
        image_unique_2 = image_unique_2.scaled(image_scale_size)
        image_similar = image_similar.scaled(image_scale_size)
        #Markers for editor 1
        self.marker_unique_1 = self.editor_1.markerDefine(
            data.QsciScintillaBase.SC_MARK_BACKGROUND, 0)
        self.marker_unique_symbol_1 = self.editor_1.markerDefine(
            image_unique_1, 1)
        self.marker_similar_1 = self.editor_1.markerDefine(
            data.QsciScintillaBase.SC_MARK_BACKGROUND, 2)
        self.marker_similar_symbol_1 = self.editor_1.markerDefine(
            image_similar, 3)
        #Set background colors only for the background markers
        self.editor_1.setMarkerBackgroundColor(self.Indicator_Unique_1_Color,
                                               self.marker_unique_1)
        self.editor_1.setMarkerBackgroundColor(self.Indicator_Similar_Color,
                                               self.marker_similar_1)
        #Margins for editor 1
        self.init_margin(self.editor_1, self.marker_unique_1,
                         self.marker_unique_symbol_1, self.marker_similar_1,
                         self.marker_similar_symbol_1)
        #Markers for editor 2
        self.marker_unique_2 = self.editor_2.markerDefine(
            data.QsciScintillaBase.SC_MARK_BACKGROUND, 0)
        self.marker_unique_symbol_2 = self.editor_2.markerDefine(
            image_unique_2, 1)
        self.marker_similar_2 = self.editor_2.markerDefine(
            data.QsciScintillaBase.SC_MARK_BACKGROUND, 2)
        self.marker_similar_symbol_2 = self.editor_2.markerDefine(
            image_similar, 3)
        #Set background colors only for the background markers
        self.editor_2.setMarkerBackgroundColor(self.Indicator_Unique_2_Color,
                                               self.marker_unique_2)
        self.editor_2.setMarkerBackgroundColor(self.Indicator_Similar_Color,
                                               self.marker_similar_2)
        #Margins for editor 2
        self.init_margin(self.editor_2, self.marker_unique_2,
                         self.marker_unique_symbol_2, self.marker_similar_2,
                         self.marker_similar_symbol_2)

    def init_indicator(self, editor, indicator, color):
        """Set the indicator settings"""
        editor.indicatorDefine(data.QsciScintillaBase.INDIC_ROUNDBOX,
                               indicator)
        editor.setIndicatorForegroundColor(color, indicator)
        editor.SendScintilla(data.QsciScintillaBase.SCI_SETINDICATORCURRENT,
                             indicator)

    def init_editor(self, editor):
        """Initialize all of the PlainEditor settings for difference displaying"""
        editor.setLexer(None)
        editor.setUtf8(True)
        editor.setIndentationsUseTabs(False)
        editor.setFont(self.DEFAULT_FONT)
        editor.setBraceMatching(data.QsciScintilla.SloppyBraceMatch)
        editor.setMatchedBraceBackgroundColor(data.QColor(255, 153, 0))
        editor.setAcceptDrops(False)
        editor.setEolMode(settings.Editor.end_of_line_mode)
        editor.setReadOnly(True)
        editor.savable = data.CanSave.NO

    def set_margin_text(self, editor, line, text):
        """Set the editor's margin text at the selected line"""
        editor.setMarginText(line, text, self.MARGIN_STYLE)

    def set_line_indicator(self, editor, line, indicator_index):
        """Set the editor's selected line color"""
        #Set the indicator
        if indicator_index == self.INDICATOR_UNIQUE_1:
            self.init_indicator(editor, self.INDICATOR_UNIQUE_1,
                                self.Indicator_Unique_1_Color)
        elif indicator_index == self.INDICATOR_UNIQUE_2:
            self.init_indicator(editor, self.INDICATOR_UNIQUE_2,
                                self.Indicator_Unique_2_Color)
        elif indicator_index == self.INDICATOR_SIMILAR:
            self.init_indicator(editor, self.INDICATOR_SIMILAR,
                                self.Indicator_Similar_Color)
        #Color the line background
        scintilla_command = data.QsciScintillaBase.SCI_INDICATORFILLRANGE
        start = editor.positionFromLineIndex(line, 0)
        length = editor.lineLength(line)
        editor.SendScintilla(scintilla_command, start, length)

    def compare(self, text_1, text_2):
        """
        Compare two text strings and display the difference
        !! This function uses Python's difflib which is not 100% accurate !!
        """
        #Store the original text
        self.text_1 = text_1
        self.text_2 = text_2
        text_1_list = text_1.split("\n")
        text_2_list = text_2.split("\n")
        #Create the difference
        differer = difflib.Differ()
        list_sum = list(differer.compare(text_1_list, text_2_list))
        #Assemble the two lists of strings that will be displayed in each editor
        list_1 = []
        line_counter_1 = 1
        line_numbering_1 = []
        line_styling_1 = []
        list_2 = []
        line_counter_2 = 1
        line_numbering_2 = []
        line_styling_2 = []
        #Flow control flags
        skip_next = False
        store_next = False
        for i, line in enumerate(list_sum):
            if store_next == True:
                store_next = False
                list_2.append(line[2:])
                line_numbering_2.append(str(line_counter_2))
                line_counter_2 += 1
                line_styling_2.append(self.INDICATOR_SIMILAR)
            elif skip_next == False:
                if line.startswith("  "):
                    #The line is the same in both texts
                    list_1.append(line[2:])
                    line_numbering_1.append(str(line_counter_1))
                    line_counter_1 += 1
                    line_styling_1.append(None)
                    list_2.append(line[2:])
                    line_numbering_2.append(str(line_counter_2))
                    line_counter_2 += 1
                    line_styling_2.append(None)
                elif line.startswith("- "):
                    #The line is unique to text 1
                    list_1.append(line[2:])
                    line_numbering_1.append(str(line_counter_1))
                    line_counter_1 += 1
                    line_styling_1.append(self.INDICATOR_UNIQUE_1)
                    list_2.append("")
                    line_numbering_2.append("")
                    line_styling_2.append(None)
                elif line.startswith("+ "):
                    #The line is unique to text 2
                    list_1.append("")
                    line_numbering_1.append("")
                    line_styling_1.append(None)
                    list_2.append(line[2:])
                    line_numbering_2.append(str(line_counter_2))
                    line_counter_2 += 1
                    line_styling_2.append(self.INDICATOR_UNIQUE_2)
                elif line.startswith("? "):
                    #The line is similar
                    if (list_sum[i - 1].startswith("- ") and len(list_sum) >
                        (i + 1) and list_sum[i + 1].startswith("+ ")
                            and len(list_sum) > (i + 2)
                            and list_sum[i + 2].startswith("? ")):
                        """
                        Line order:
                            - ...
                            ? ...
                            + ...
                            ? ...
                        """
                        #Lines have only a few character difference, skip the
                        #first '?' and handle the next '?' as a "'- '/'+ '/'? '" sequence
                        pass
                    elif list_sum[i - 1].startswith("- "):
                        #Line in text 1 has something added
                        """
                        Line order:
                            - ...
                            ? ...
                            + ...
                        """
                        line_styling_1[len(line_numbering_1) -
                                       1] = self.INDICATOR_SIMILAR

                        list_2.pop()
                        line_numbering_2.pop()
                        line_styling_2.pop()
                        store_next = True
                    elif list_sum[i - 1].startswith("+ "):
                        #Line in text 2 has something added
                        """
                        Line order:
                            - ...
                            + ...
                            ? ...
                        """
                        list_1.pop()
                        line_numbering_1.pop()
                        line_styling_1.pop()
                        line_styling_1[len(line_numbering_1) -
                                       1] = self.INDICATOR_SIMILAR

                        pop_index_2 = (len(line_numbering_2) - 1) - 1
                        list_2.pop(pop_index_2)
                        line_numbering_2.pop(pop_index_2)
                        line_styling_2.pop()
                        line_styling_2.pop()
                        line_styling_2.append(self.INDICATOR_SIMILAR)
            else:
                skip_next = False
        #Display the results
        self.editor_1.setText("\n".join(list_1))
        self.editor_2.setText("\n".join(list_2))
        #Set margins and style for both editors
        for i, line in enumerate(line_numbering_1):
            self.set_margin_text(self.editor_1, i, line)
            line_styling = line_styling_1[i]
            if line_styling != None:
                if line_styling == self.INDICATOR_SIMILAR:
                    self.editor_1.markerAdd(i, self.marker_similar_1)
                    self.editor_1.markerAdd(i, self.marker_similar_symbol_1)
                else:
                    self.editor_1.markerAdd(i, self.marker_unique_1)
                    self.editor_1.markerAdd(i, self.marker_unique_symbol_1)
        for i, line in enumerate(line_numbering_2):
            self.set_margin_text(self.editor_2, i, line)
            line_styling = line_styling_2[i]
            if line_styling != None:
                if line_styling == self.INDICATOR_SIMILAR:
                    self.editor_2.markerAdd(i, self.marker_similar_2)
                    self.editor_2.markerAdd(i, self.marker_similar_symbol_2)
                else:
                    self.editor_2.markerAdd(i, self.marker_unique_2)
                    self.editor_2.markerAdd(i, self.marker_unique_symbol_2)
        #Check if there were any differences
        if (any(line_styling_1) == False and any(line_styling_2) == False):
            self.main_form.display.repl_display_message(
                "No differences between texts.",
                message_type=data.MessageType.SUCCESS)
        else:
            #Count the number of differences
            difference_counter_1 = 0
            #Similar line count is the same in both editor line stylings
            similarity_counter = 0
            for diff in line_styling_1:
                if diff != None:
                    if diff == self.INDICATOR_SIMILAR:
                        similarity_counter += 1
                    else:
                        difference_counter_1 += 1
            difference_counter_2 = 0
            for diff in line_styling_2:
                if diff != None:
                    if diff == self.INDICATOR_SIMILAR:
                        #Skip the similar line, which were already counter above
                        continue
                    else:
                        difference_counter_2 += 1
            #Display the differences/similarities messages
            self.main_form.display.repl_display_message(
                "{:d} differences found in '{:s}'!".format(
                    difference_counter_1, self.text_1_name),
                message_type=data.MessageType.DIFF_UNIQUE_1)
            self.main_form.display.repl_display_message(
                "{:d} differences found in '{:s}'!".format(
                    difference_counter_2, self.text_2_name),
                message_type=data.MessageType.DIFF_UNIQUE_2)
            self.main_form.display.repl_display_message(
                "{:d} similarities found between documents!".format(
                    similarity_counter, self.text_2_name),
                message_type=data.MessageType.DIFF_SIMILAR)
        self._update_margins()

    def find_next_unique_1(self):
        """Find and scroll to the first unique 1 difference"""
        self.focused_editor = self.editor_1
        cursor_line, cursor_index = self.editor_1.getCursorPosition()
        next_unique_diff_line = self.editor_1.markerFindNext(
            cursor_line + 1, 0b0011)
        #Correct the line numbering to the 1..line_count display
        next_unique_diff_line += 1
        self.editor_1.goto_line(next_unique_diff_line, skip_repl_focus=False)
        self.editor_2.goto_line(next_unique_diff_line, skip_repl_focus=False)
        #Check if we are back at the start of the document
        if next_unique_diff_line == 0:
            self.main_form.display.repl_display_message(
                "Scrolled back to the start of the document!",
                message_type=data.MessageType.DIFF_UNIQUE_1)
            self.main_form.display.write_to_statusbar(
                "Scrolled back to the start of the document!")

    def find_next_unique_2(self):
        """Find and scroll to the first unique 2 difference"""
        self.focused_editor = self.editor_2
        cursor_line, cursor_index = self.editor_2.getCursorPosition()
        next_unique_diff_line = self.editor_2.markerFindNext(
            cursor_line + 1, 0b0011)
        #Correct the line numbering to the 1..line_count display
        next_unique_diff_line += 1
        self.editor_1.goto_line(next_unique_diff_line, skip_repl_focus=False)
        self.editor_2.goto_line(next_unique_diff_line, skip_repl_focus=False)
        #Check if we are back at the start of the document
        if next_unique_diff_line == 0:
            self.main_form.display.repl_display_message(
                "Scrolled back to the start of the document!",
                message_type=data.MessageType.DIFF_UNIQUE_2)
            self.main_form.display.write_to_statusbar(
                "Scrolled back to the start of the document!")

    def find_next_similar(self):
        """Find and scroll to the first similar line"""
        self.focused_editor = self.editor_1
        cursor_line, cursor_index = self.editor_1.getCursorPosition()
        next_unique_diff_line = self.editor_1.markerFindNext(
            cursor_line + 1, 0b1100)
        #Correct the line numbering to the 1..line_count display
        next_unique_diff_line += 1
        self.editor_1.goto_line(next_unique_diff_line, skip_repl_focus=False)
        self.editor_2.goto_line(next_unique_diff_line, skip_repl_focus=False)
        #Check if we are back at the start of the document
        if next_unique_diff_line == 0:
            self.main_form.display.repl_display_message(
                "Scrolled back to the start of the document!",
                message_type=data.MessageType.DIFF_SIMILAR)
            self.main_form.display.write_to_statusbar(
                "Scrolled back to the start of the document!")

    def add_corner_buttons(self):
        # Unique 1 button
        self.icon_manipulator.add_corner_button(
            functions.create_icon("tango_icons/diff-unique-1.png"),
            "Scroll to next unique line\nin document: '{:s}'".format(
                self.text_1_name), self.find_next_unique_1)
        # Unique 2 button
        self.icon_manipulator.add_corner_button(
            functions.create_icon("tango_icons/diff-unique-2.png"),
            "Scroll to next unique line\nin document: '{:s}'".format(
                self.text_2_name), self.find_next_unique_2)
        # Similar button
        self.icon_manipulator.add_corner_button(
            functions.create_icon("tango_icons/diff-similar.png"),
            "Scroll to next similar line\nin both documents",
            self.find_next_similar)

    def set_theme(self, theme):
        def set_editor_theme(editor):
            if theme == themes.Air:
                editor.resetFoldMarginColors()
            elif theme == themes.Earth:
                editor.setFoldMarginColors(theme.FoldMargin.ForeGround,
                                           theme.FoldMargin.BackGround)
            editor.setMarginsForegroundColor(theme.LineMargin.ForeGround)
            editor.setMarginsBackgroundColor(theme.LineMargin.BackGround)
            editor.SendScintilla(data.QsciScintillaBase.SCI_STYLESETBACK,
                                 data.QsciScintillaBase.STYLE_DEFAULT,
                                 theme.Paper.Default)
            editor.SendScintilla(data.QsciScintillaBase.SCI_STYLESETBACK,
                                 data.QsciScintillaBase.STYLE_LINENUMBER,
                                 theme.LineMargin.BackGround)
            editor.SendScintilla(data.QsciScintillaBase.SCI_SETCARETFORE,
                                 theme.Cursor)
            editor.choose_lexer("text")

        set_editor_theme(self.editor_1)
        set_editor_theme(self.editor_2)
示例#15
0
 def __init__(self, parent, main_form, repl_master):
     #Initialize superclass, from which the current class is inherited, THIS MUST BE DONE SO THAT THE SUPERCLASS EXECUTES ITS __init__ !!!!!!
     super().__init__(parent)
     # Set default font
     self.setFont(data.get_current_font())
     #Save the reference to the parent(main window)
     self._parent = parent
     self.main_form = main_form
     #Save the reference to the REPL object
     self.repl_master = repl_master
     #Hide the horizontal and show the vertical scrollbar
     self.SendScintilla(data.QsciScintillaBase.SCI_SETVSCROLLBAR, True)
     self.SendScintilla(data.QsciScintillaBase.SCI_SETHSCROLLBAR, False)
     #Hide the margin
     self.setMarginWidth(1, 0)
     #Autoindentation enabled when using "Enter" to indent to the same level as the previous line
     self.setAutoIndent(True)
     #Tabs are spaces by default
     self.setIndentationsUseTabs(False)
     #Set tab space indentation width
     self.setTabWidth(settings.Editor.tab_width)
     #Set encoding format to UTF-8 (Unicode)
     self.setUtf8(True)
     #Set brace matching
     self.setBraceMatching(data.QsciScintilla.SloppyBraceMatch)
     self.setMatchedBraceBackgroundColor(data.QColor(255, 153, 0))
     #Tabs are spaces by default
     self.setIndentationsUseTabs(False)
     #Set backspace to delete by tab widths
     self.setBackspaceUnindents(True)
     #Disable drops
     self.setAcceptDrops(False)
     #Set line endings to be Unix style ("\n")
     self.setEolMode(settings.Editor.end_of_line_mode)
     #Set the initial zoom factor
     self.zoomTo(settings.Editor.zoom_factor)
     """
     Functionality copied from the CustomEditor to copy some of 
     the neede editing functionality like commenting, ...
     """
     # Add the attributes needed to implement the line nist
     self.line_list = components.LineList(self, self.text())
     # Add the needed functions assigned from the CustomEditor
     self.set_theme = functools.partial(CustomEditor.set_theme, self)
     self.set_line = functools.partial(CustomEditor.set_line, self)
     self.set_lines = functools.partial(CustomEditor.set_lines, self)
     self.toggle_comment_uncomment = functools.partial(CustomEditor.toggle_comment_uncomment, self)
     self.comment_line = functools.partial(CustomEditor.comment_line, self)
     self.comment_lines = functools.partial(CustomEditor.comment_lines, self)
     self.uncomment_line = functools.partial(CustomEditor.uncomment_line, self)
     self.uncomment_lines = functools.partial(CustomEditor.uncomment_lines, self)
     self.prepend_to_line = functools.partial(CustomEditor.prepend_to_line, self)
     self.prepend_to_lines = functools.partial(CustomEditor.prepend_to_lines, self)
     self.replace_line = functools.partial(CustomEditor.replace_line, self)
     self.get_line = functools.partial(CustomEditor.get_line, self)
     self.check_line_numbering = functools.partial(CustomEditor.check_line_numbering, self)
     self.text_to_list = functools.partial(CustomEditor.text_to_list, self)
     self.list_to_text = functools.partial(CustomEditor.list_to_text, self)
     # Add the function and connect the signal to update the line/column positions
     self.cursorPositionChanged.connect(self._signal_editor_cursor_change)
     #Set the lexer to python
     self.set_lexer()
     #Set the initial autocompletions
     self.update_autocompletions()
     #Setup the LineList object that will hold the custom editor text as a list of lines
     self.line_list = components.LineList(self, self.text())
     self.textChanged.connect(self.text_changed)
示例#16
0
文件: baselexer.py 项目: Mr-ZBin/ExCo
class Nim(data.QsciLexerCustom):
    """
    Custom lexer for the Nim programming language
    """
    styles = {
        "Default" : 0,
        "Comment" : 1,
        "BasicKeyword" : 2,
        "TopKeyword" : 3,
        "String" :  4,
        "LongString" : 5,
        "Number" :  6,
        "Pragma" : 7,
        "Operator" : 8,
        "Unsafe" : 9,
        "Type" : 10,
        "DocumentationComment" : 11,
        "Definition" : 12,
        "Class" : 13,
        "KeywordOperator" : 14,
        "CharLiteral" :  15,
        "CaseOf" :  16,
        "UserKeyword" :  17,
        "MultilineComment" :  18,
        "MultilineDocumentation" : 19
    }
    
    #Class variables
    default_color       = data.QColor(data.theme.Font.Nim.Default[1])
    default_paper       = data.QColor(data.theme.Paper.Nim.Default)
    default_font        = data.QFont(data.current_font_name, data.current_font_size)
    #Basic keywords and built-in procedures and templates
    basic_keyword_list  = [
        "as", "atomic", "bind", "sizeof", 
        "break", "case", "continue", "converter",
        "discard", "distinct", "do", "echo", "elif", "else", "end",
        "except", "finally", "for", "from", "defined", 
        "if", "interface", "iterator", "macro", "method", "mixin", 
        "of", "out", "proc", "func", "raise", "ref", "result", 
        "return", "template", "try", "inc", "dec", "new", "quit", 
        "while", "with", "without", "yield", "true", "false", 
        "assert", "min", "max", "newseq", "len", "pred", "succ", 
        "contains", "cmp", "add", "del","deepcopy", "shallowcopy", 
        "abs", "clamp", "isnil", "open", "reopen", "close","readall", 
        "readfile", "writefile", "endoffile", "readline", "writeline", 
    ]
    #Custom keyword created with templates/macros
    user_keyword_list = [
        "class", "namespace", "property",
    ]
    #Keywords that define a proc-like definition
    def_keyword_list = ["proc", "method", "func", "template", "macro", "converter", "iterator"]
    #Keywords that can define blocks
    top_keyword_list = [
        "block", "const", "export", "import", "include", "let", 
        "static", "type", "using", "var", "when", 
    ]
    #Keywords that might be unsafe/dangerous
    unsafe_keyword_list = [
        "asm", "addr", "cast", "ptr", "pointer", "alloc", "alloc0",
        "allocshared0", "dealloc", "realloc", "nil", "gc_ref", 
        "gc_unref", "copymem", "zeromem", "equalmem", "movemem", 
        "gc_disable", "gc_enable", 
    ]
    #Built-in types
    type_keyword_list = [
        "int", "int8", "int16", "int32", "int64",
        "uint", "uint8", "uint16", "uint32", "uint64",
        "float", "float32", "float64", "bool", "char",
        "string", "cstring", "pointer", "ordinal", "ptr",
        "ref", "expr", "stmt", "typedesc", "void",
        "auto", "any", "untyped", "typed", "somesignedint",
        "someunsignedint", "someinteger", "someordinal", "somereal", "somenumber",
        "range", "array", "openarray", "varargs", "seq",
        "set", "slice", "shared", "guarded", "byte",
        "natural", "positive", "rootobj", "rootref", "rooteffect",
        "timeeffect", "ioeffect", "readioeffect", "writeioeffect", "execioeffect",
        "exception", "systemerror", "ioerror", "oserror", "libraryerror",
        "resourceexhaustederror", "arithmeticerror", "divbyzeroerror", "overflowerror", 
        "accessviolationerror", "assertionerror", "valueerror", "keyerror", 
        "outofmemerror", "indexerror", "fielderror", "rangeerror", "stackoverflowerror", 
        "reraiseerror", "objectassignmenterror", "objectconversionerror", "floatingpointerror", 
        "floatinvalidoperror", "floatdivbyzeroerror", "floatoverflowerror",
        "floatunderflowerror", "floatinexacterror", "deadthreaderror", "tresult", "endianness",
        "taintedstring", "libhandle", "procaddr", "byteaddress", "biggestint",
        "biggestfloat", "clong", "culong", "cchar", "cschar",
        "cshort", "cint", "csize", "clonglong", "cfloat",
        "cdouble", "clongdouble", "cuchar", "cushort", "cuint",
        "culonglong", "cstringarray", "pfloat32", "pfloat64", "pint64",
        "pint32", "gc_strategy", "pframe", "tframe", "file",
        "filemode", "filehandle", "thinstance", "aligntype", "refcount",
        "object", "tuple", "enum",
    ]
    #Sign operators
    operator_list = [
        "=", "+", "-", "*", "/", "<", ">", "@", "$", ".",
        "~", "&", "%", "|", "!", "?", "^", ".", ":", "\"",
    ]
    #Keyword operators
    keyword_operator_list = [
        "and", "or", "not", "xor", "shl", "shr", "div", "mod", 
        "in", "notin", "is", "isnot",
    ]
    splitter = re.compile(r"(\{\.|\.\}|\#|\'|\"\"\"|\n|\s+|\w+|\W)")
    #Characters that autoindent one level on pressing Return/Enter
    autoindent_characters = [":", "="]

    def __init__(self, parent=None):
        """Overridden initialization"""
        #Initialize superclass
        super().__init__()
        #Set the default style values
        self.setDefaultColor(self.default_color)
        self.setDefaultPaper(self.default_paper)
        self.setDefaultFont(self.default_font)
        #Reset autoindentation style
        self.setAutoIndentStyle(0)
        #Set the theme
        self.set_theme(data.theme)
    
    def language(self):
        return "Nim"
    
    def description(self, style):
        if style < len(self.styles):
            description = "Custom lexer for the Nim programming languages"
        else:
            description = ""
        return description
    
    def defaultStyle(self):
        return self.styles["Default"]
    
    def braceStyle(self):
        return self.styles["Default"]
    
    def defaultFont(self, style):
        return data.QFont(data.current_font_name, data.current_font_size)
    
    def set_theme(self, theme):
        for style in self.styles.keys():
            # Papers
            self.setPaper(
                data.QColor(theme.Paper.Nim.Default), 
                self.styles[style]
            )
            # Fonts
            set_font(self, style, getattr(theme.Font.Nim, style))
        
    
    def styleText(self, start, end):
        """
        Overloaded method for styling text.
        NOTE:
            Very slow if done in Python!
            Using the Cython version is better.
            The fastest would probably be adding the lexer directly into
            the QScintilla source. Maybe never :-)
        """
        #Style in pure Python, VERY SLOW!
        editor = self.editor()
        if editor is None:
            return
        #Initialize the styling
        self.startStyling(start)
        #Scintilla works with bytes, so we have to adjust the start and end boundaries
        text = bytearray(editor.text().lower(), "utf-8")[start:end].decode("utf-8")
        #Loop optimizations
        setStyling      = self.setStyling
        basic_kw_list   = self.basic_keyword_list
        user_kw_list    = self.user_keyword_list
        def_kw_list     = self.def_keyword_list
        top_kw_list     = self.top_keyword_list
        unsafe_kw_list  = self.unsafe_keyword_list
        operator_list   = self.operator_list
        keyword_operator_list = self.keyword_operator_list
        type_kw_list    = self.type_keyword_list
        DEF     = self.styles["Default"]
        B_KWD   = self.styles["BasicKeyword"]
        T_KWD   = self.styles["TopKeyword"]
        COM     = self.styles["Comment"]
        STR     = self.styles["String"]
        L_STR   = self.styles["LongString"]
        NUM     = self.styles["Number"]
        MAC     = self.styles["Pragma"]
        OPE     = self.styles["Operator"]
        UNS     = self.styles["Unsafe"]
        TYP     = self.styles["Type"]
        D_COM   = self.styles["DocumentationComment"]
        DEFIN   = self.styles["Definition"]
        CLS     = self.styles["Class"]
        KOP     = self.styles["KeywordOperator"]
        CHAR    = self.styles["CharLiteral"]
        OF      = self.styles["CaseOf"]
        U_KWD   = self.styles["UserKeyword"]
        M_COM   = self.styles["MultilineComment"]
        M_DOC   = self.styles["MultilineDocumentation"]
        #Initialize various states and split the text into tokens
        commenting          = False
        doc_commenting      = False
        multi_doc_commenting= False
        new_commenting      = False
        stringing           = False
        long_stringing      = False
        char_literal        = False
        pragmaing           = False
        case_of             = False
        cls_descrition      = False
        tokens = [(token, len(bytearray(token, "utf-8"))) for token in self.splitter.findall(text)]
        #Check if there is a style(comment, string, ...) stretching on from the previous line
        if start != 0:
            previous_style = editor.SendScintilla(editor.SCI_GETSTYLEAT, start - 1)
            if previous_style == L_STR:
                long_stringing = True
            elif previous_style == MAC:
                pragmaing = True
            elif previous_style == M_COM:
                new_commenting = True
            elif previous_style == M_DOC:
                multi_doc_commenting = True
        #Style the tokens accordingly
        for i, token in enumerate(tokens):
#                print(str(token) + "  " + str(i))
            if commenting == True:
                #Continuation of comment
                setStyling(token[1], COM)
                #Check if comment ends
                if "\n" in token[0]:
                    commenting = False
            elif doc_commenting == True:
                #Continuation of comment
                setStyling(token[1], D_COM)
                #Check if comment ends
                if "\n" in token[0]:
                    doc_commenting = False
            elif new_commenting == True:
                #Continuation of comment
                setStyling(token[1], M_COM)
                #Check if comment ends
                if "#" in token[0] and "]" in tokens[i-1][0]:
                    new_commenting = False
            elif multi_doc_commenting == True:
                #Continuation of comment
                setStyling(token[1], M_DOC)
                #Check if comment ends
                if "#" in token[0] and "#" in tokens[i-1][0] and "]" in tokens[i-2][0]:
                    multi_doc_commenting = False
            elif stringing == True:
                #Continuation of a string
                setStyling(token[1], STR)
                #Check if string ends
                if token[0] == "\"" and (tokens[i-1][0] != "\\") or "\n" in token[0]:
                    stringing = False
            elif long_stringing == True:
                #Continuation of a string
                setStyling(token[1], L_STR)
                #Check if string ends
                if token[0] == "\"\"\"":
                    long_stringing = False
            elif char_literal == True:
                #Check if string ends
                if ("\n" in token[0] or 
                    " " in token[0] or
                    "(" in token[0] or
                    ")" in token[0] or
                    "," in token[0] or
                    token[0] in operator_list):
                    #Do not color the separator
                    setStyling(token[1], DEF)
                    char_literal = False
                elif token[0] == "'":
                    #Continuation of a character
                    setStyling(token[1], CHAR)
                    char_literal = False
                else:
                    setStyling(token[1], CHAR)
            elif pragmaing == True:
                #Continuation of a string
                setStyling(token[1], MAC)
                #Check if string ends
                if token[0] == ".}":
                    pragmaing = False
            elif case_of == True:
                #'Case of' parameter
                if token[0] == ":" or "\n" in token[0]:
                    setStyling(token[1], DEF)
                    case_of = False
                else:
                    setStyling(token[1], OF)
            elif cls_descrition == True:
                #Class/namespace description
                if token[0] == ":" or "\n" in token[0]:
                    setStyling(token[1], DEF)
                    cls_descrition = False
                else:
                    setStyling(token[1], CLS)
            elif token[0] == "\"\"\"":
                #Start of a multi line (long) string
                setStyling(token[1], L_STR)
                long_stringing = True
            elif token[0] == "{.":
                #Start of a multi line (long) string
                setStyling(token[1], MAC)
                pragmaing = True
            elif token[0] == "\"":
                #Start of a string
                setStyling(token[1], STR)
                stringing = True
            elif token[0] == "'":
                #Start of a string
                setStyling(token[1], CHAR)
                char_literal = True
            elif token[0] in basic_kw_list:
                #Basic keyword
                setStyling(token[1], B_KWD)
                try:
                    if ((token[0] == "of" and "\n" in tokens[i-2][0]) or
                        ((token[0] == "of" and "\n" in tokens[i-1][0]))):
                        #Start of a CASE
                        case_of = True
                except IndexError:
                    case_of = False
            elif token[0] in user_kw_list:
                #User keyword
                setStyling(token[1], U_KWD)
            elif token[0] in top_kw_list:
                #Top keyword
                setStyling(token[1], T_KWD)
            elif token[0] in unsafe_kw_list:
                #Unsafe/danger keyword
                setStyling(token[1], UNS)
            elif token[0] in operator_list:
                #Operator
                setStyling(token[1], OPE)
            elif token[0] in keyword_operator_list:
                #Operator
                setStyling(token[1], KOP)
            elif token[0] in type_kw_list:
                #Operator
                setStyling(token[1], TYP)
            elif token[0] == "#":
                #Start of a comment or documentation comment
                if len(tokens) > i+2 and tokens[i+1][0] == "#" and tokens[i+2][0] == "[":
                    setStyling(token[1], M_DOC)
                    multi_doc_commenting = True
                elif len(tokens) > i+1 and tokens[i+1][0] == "#":
                    setStyling(token[1], D_COM)
                    doc_commenting = True
                elif len(tokens) > i+1 and tokens[i+1][0] == "[":
                    setStyling(token[1], M_COM)
                    new_commenting = True
                else:
                    setStyling(token[1], COM)
                    commenting = True
            elif (i > 1) and (("\n" in tokens[i-2][0]) or ("  " in tokens[i-2][0])) and (tokens[i-1][0] == "of"):
                #Case of statement
                case_of = True
                setStyling(token[1], OF)
            elif functions.is_number(token[0][0]):
                #Number
                #Check only the first character, because Nim has those weird constants e.g.: 12u8, ...)
                setStyling(token[1], NUM)
            elif ((i > 1) and (tokens[i-2][0] in user_kw_list) and token[0][0].isalpha()):
                #Class-like definition
                setStyling(token[1], CLS)
                cls_descrition = True
            elif (((i > 1) and (tokens[i-2][0] in def_kw_list and tokens[i-1][0] != "(") and token[0][0].isalpha()) or
                    ((i > 2) and (tokens[i-3][0] in def_kw_list and tokens[i-1][0] == '`') and token[0][0].isalpha())):
                #Proc-like definition
                setStyling(token[1], DEFIN)
            else:
                setStyling(token[1], DEF)
示例#17
0
        def __init__(self,
                     name,
                     picture,
                     scale_factor=1.0,
                     function=None,
                     key_combination=None,
                     starting_position=None,
                     end_position=None,
                     parent=None):
            super().__init__(parent)

            self.name = name
            self.scale_factor = scale_factor
            self.key_combination = key_combination
            self.animating = False
            self.starting_position = starting_position
            self.end_position = end_position
            self.disable()
            self.properties = {}
            # Set default font
            self.setFont(data.get_current_font())
            # Button image
            self.button_image = data.QPixmap(
                os.path.join(data.resources_directory, picture))
            adjusted_size = self.DEFAULT_SIZE * self.scale_factor
            self.button_image = self.button_image.scaled(
                functions.create_size(
                    math.ceil(adjusted_size),
                    math.ceil(adjusted_size),
                ),
                transformMode=data.Qt.SmoothTransformation)

            width, height = components.HexBuilder.get_single_hex_size(
                adjusted_size, 2)

            def create_base_image():
                hex_image = data.QImage(
                    functions.create_size(width, height),
                    data.QImage.Format_ARGB32_Premultiplied)
                hex_image.fill(data.Qt.transparent)
                qpainter = data.QPainter(hex_image)
                qpainter.setRenderHints(data.QPainter.Antialiasing
                                        | data.QPainter.TextAntialiasing
                                        | data.QPainter.SmoothPixmapTransform)
                hb = components.HexBuilder(
                    qpainter,
                    (width / 2, height / 2),
                    self.DEFAULT_SIZE,
                    self.scale_factor,
                    fill_color=data.theme.Settings_Hex_Background,
                    line_width=2,
                    line_color=data.QColor(64, 64, 64),
                )
                hb.create_grid(False)
                qpainter.end()
                return data.QPixmap.fromImage(hex_image)

            self.hex_image = create_base_image()
            self.hex_image = self.hex_image.scaled(
                functions.create_size(
                    math.ceil(self.hex_image.size().width() *
                              self.scale_factor),
                    math.ceil(self.hex_image.size().height() *
                              self.scale_factor),
                ),
                transformMode=data.Qt.SmoothTransformation)

            # Green hex background
            def create_color_image(color):
                hex_image = data.QImage(
                    functions.create_size(width, height),
                    data.QImage.Format_ARGB32_Premultiplied)
                hex_image.fill(data.Qt.transparent)
                qpainter = data.QPainter(hex_image)
                qpainter.setRenderHints(data.QPainter.Antialiasing
                                        | data.QPainter.TextAntialiasing
                                        | data.QPainter.SmoothPixmapTransform)
                hb = components.HexBuilder(
                    qpainter,
                    (width / 2, height / 2),
                    self.DEFAULT_SIZE,
                    self.scale_factor,
                    fill_color=color,
                    line_width=0,
                    line_color=data.QColor(0, 0, 0),
                )
                hb.create_grid(False)
                qpainter.end()
                return data.QPixmap.fromImage(hex_image)

            self.hex_image_green = create_color_image(data.QColor(
                138, 226, 52))
            self.hex_image_green = self.hex_image_green.scaled(
                functions.create_size(
                    math.ceil(self.hex_image_green.size().width() *
                              self.scale_factor) - 1,
                    math.ceil(self.hex_image_green.size().height() *
                              self.scale_factor) - 1,
                ),
                transformMode=data.Qt.SmoothTransformation)
            # Red hex background
            self.hex_image_red = create_color_image(data.QColor(239, 41, 41))
            self.hex_image_red = self.hex_image_red.scaled(
                functions.create_size(
                    math.ceil(self.hex_image_red.size().width() *
                              self.scale_factor) - 1,
                    math.ceil(self.hex_image_red.size().height() *
                              self.scale_factor) - 1,
                ),
                transformMode=data.Qt.SmoothTransformation)

            scaled_size = functions.create_size(
                self.hex_image.size().width(),
                self.hex_image.size().height(),
            )
            image = data.QImage(
                scaled_size,
                data.QImage.Format_ARGB32_Premultiplied,
            )
            image.fill(data.Qt.transparent)
            button_painter = data.QPainter(image)
            button_painter.setCompositionMode(
                data.QPainter.CompositionMode_SourceOver)
            button_painter.setOpacity(1.0)
            # Adjust inner button positioning according to the scale
            x = (self.hex_image.width() - self.button_image.width()) / 2
            y = (self.hex_image.height() - self.button_image.height()) / 2
            button_painter.drawPixmap(0, 0, self.hex_image)

            button_painter.drawPixmap(x, y, self.button_image)
            button_painter.end()

            # Set properites
            self.setParent(parent)
            self.setPixmap(data.QPixmap.fromImage(image))
            self.setGeometry(0, 0, int(image.width() * self.scale_factor),
                             int(image.height() * self.scale_factor))
            self.setMask(self.hex_image.mask())
            self.setScaledContents(True)
            # Set the non-enlarged dimensions
            self.original_size = (self.geometry().width(),
                                  self.geometry().height())

            # Set the initial color state
            self.current_color = "default"
示例#18
0
class RouterOS(data.QsciLexerCustom):
    """
    Custom lexer for the RouterOS syntax for MikroTik routers (WinBox)
    """
    styles = {
        "Default": 0,
        "Operator": 1,
        "Comment": 2,
        "Keyword1": 3,
        "Keyword2": 4,
        "Keyword3": 5,
    }
    #Class variables
    default_color = data.QColor(data.theme.Font.RouterOS.Default[1])
    default_paper = data.QColor(data.theme.Paper.RouterOS.Default)
    default_font = data.QFont('Courier', 10)
    #All keywords, operators, ...
    operator_list = [
        '!', '$', '(', ')', ',', ':', '[', ']', '{', '|', '}', "="
    ]
    comment_list = ['#']
    keyword1_list = [
        'ac-name', 'accept', 'accessible-via-web', 'account-local-traffic',
        'accounting', 'action', 'active-flow-timeout', 'active-mode',
        'add-default-route', 'address-list', 'address-pool', 'address',
        'addresses-per-mac', 'admin-mac', 'advertise-dns',
        'advertise-mac-address', 'ageing-time', 'allocate-udp-ports-from',
        'allow-disable-external-interface', 'allow-guests',
        'allow-remote-requests', 'allow', 'allowed-number',
        'always-from-cache', 'area-id', 'area', 'arp', 'as', 'audio-max',
        'audio-min', 'audio-monitor', 'auth-algorithms', 'auth-method', 'auth',
        'authenticate', 'authentication-password', 'authentication-protocol',
        'authentication-types', 'authentication', 'authoritative', 'auto-mac',
        'auto-negotiation', 'auto-send-supout', 'automatic-supout',
        'autonomous', 'backup-allowed', 'baud-rate', 'bidirectional-timeout',
        'blank-interval', 'bootp-support', 'bridge-mode', 'bridge',
        'broadcast-addresses', 'broadcast', 'bsd-syslog', 'cable-settings',
        'cache-administrator', 'cache-entries', 'cache-hit-dscp',
        'cache-max-ttl', 'cache-on-disk', 'cache-size', 'certificate', 'chain',
        'change-tcp-mss', 'channel-time', 'channel', 'check-interval',
        'cipher', 'client-to-client-reflection', 'comment', 'connection-bytes',
        'connection-idle-timeout', 'connection-mark', 'connection-state',
        'contact', 'contrast', 'cpu', 'data-bits', 'default-ap-tx-limit',
        'default-authentication', 'default-client-tx-limit',
        'default-forwarding', 'default-group', 'default-profile',
        'default-route-distance', 'default', 'dh-group', 'dhcp-option',
        'dial-on-demand', 'directory', 'disable-running-check', 'disabled',
        'disk-file-count', 'disk-file-name', 'disk-lines-per-file',
        'disk-stop-on-full', 'display-time', 'distance', 'distribute-default',
        'distribute-for-default-route', 'dns-name', 'dns-server', 'domain',
        'dpd-interval', 'dpd-maximum-failures', 'dst-address-list',
        'dst-address', 'dst-delta', 'dst-end', 'dst-port', 'dst-start',
        'dynamic-label-range', 'e', 'eap-methods', 'enabled', 'enc-algorithm',
        'enc-algorithms', 'encryption-password', 'encryption-protocol',
        'engine-id', 'exchange-mode', 'exclude-groups', 'file-limit',
        'file-name', 'filter-ip-address', 'filter-ip-protocol',
        'filter-mac-address', 'filter-mac-protocol', 'filter-mac',
        'filter-port', 'filter-stream', 'flow-control', 'forward-delay',
        'frame-size', 'frames-per-second', 'from', 'full-duplex',
        'garbage-timer', 'gateway-class', 'gateway-keepalive',
        'gateway-selection', 'gateway', 'generate-policy', 'generic-timeout',
        'group-ciphers', 'group-key-update', 'hash-algorithm', 'hide-ssid',
        'hop-limit', 'hotspot-address', 'html-directory',
        'http-cookie-lifetime', 'http-proxy', 'i', 'icmp-timeout',
        'idle-timeout', 'ignore-as-path-len', 'in-filter', 'in-interface',
        'inactive-flow-timeout', 'instance', 'interface', 'interfaces',
        'interim-update', 'interval', 'ipsec-protocols', 'jump-target',
        'keep-max-sms', 'keepalive-timeout', 'kind', 'l2mtu',
        'latency-distribution-scale', 'lease-time', 'level', 'lifebytes',
        'lifetime', 'line-count', 'list', 'local-address', 'location',
        'log-prefix', 'login-by', 'login', 'loop-detect', 'lsr-id',
        'mac-address', 'managed-address-configuration',
        'management-protection-key', 'management-protection', 'manycast',
        'max-cache-size', 'max-client-connections', 'max-connections',
        'max-fresh-time', 'max-message-age', 'max-mru', 'max-mtu',
        'max-server-connections', 'max-sessions', 'max-station-count',
        'max-udp-packet-size', 'memory-limit', 'memory-lines', 'memory-scroll',
        'memory-stop-on-full', 'metric-bgp', 'metric-connected',
        'metric-default', 'metric-ospf', 'metric-other-ospf', 'metric-rip',
        'metric-static', 'min-rx', 'mode', 'mpls-mtu', 'mq-pfifo-limit',
        'mrru', 'mtu', 'multi-cpu', 'multicast', 'multiple-channels',
        'multiplier', 'my-id-user-fqdn', 'name', 'nat-traversal', 'netmask',
        'network', 'new-connection-mark', 'new-packet-mark',
        'new-routing-mark', 'no-ping-delay', 'note', 'ntp-server', 'on-backup',
        'on-master', 'only-headers', 'only-one', 'origination-interval',
        'other-configuration', 'out-filter', 'out-interface', 'page-refresh',
        'parent-proxy-port', 'parent-proxy', 'parent', 'parity', 'passthrough',
        'password', 'path-vector-limit', 'paypal-accept-pending',
        'paypal-allowed', 'paypal-secure-response', 'permissions',
        'pfifo-limit', 'pfs-group', 'policy', 'port', 'ports',
        'preemption-mode', 'preferred-gateway', 'preferred-lifetime', 'prefix',
        'primary-ntp', 'primary-server', 'priority', 'profile',
        'propagate-ttl', 'proposal-check', 'proposal',
        'proprietary-extensions', 'protocol-mode', 'protocol',
        'query-interval', 'query-response-interval', 'queue', 'quick-leave',
        'ra-delay', 'ra-interval', 'ra-lifetime', 'radius-eap-accounting',
        'radius-mac-accounting', 'radius-mac-authentication',
        'radius-mac-caching', 'radius-mac-format', 'radius-mac-mode', 'ranges',
        'rate-limit', 'reachable-time', 'read-access', 'read-only',
        'receive-all', 'receive-enabled', 'receive-errors', 'red-avg-packet',
        'red-burst', 'red-limit', 'red-max-threshold', 'red-min-threshold',
        'redistribute-bgp', 'redistribute-connected', 'redistribute-ospf',
        'redistribute-other-bgp', 'redistribute-other-ospf',
        'redistribute-rip', 'redistribute-static', 'remember',
        'remote-address', 'remote-ipv6-prefix-pool', 'remote-port', 'remote',
        'require-client-certificate', 'retransmit-interval', 'router-id',
        'routing-mark', 'routing-table', 'sa-dst-address', 'sa-src-address',
        'scope', 'secondary-ntp', 'secondary-server', 'secret',
        'security-profile', 'security', 'send-initial-contact',
        'serialize-connections', 'servers', 'service-name', 'set-system-time',
        'sfq-allot', 'sfq-perturb', 'shared-users', 'show-at-login',
        'show-dummy-rule', 'signup-allowed', 'sip-direct-media', 'skin',
        'smtp-server', 'source', 'speed', 'split-user-domain',
        'src-address-list', 'src-address', 'src-port', 'ssid-all', 'ssid',
        'state-after-reboot', 'static-algo-0', 'static-algo-1',
        'static-algo-2', 'static-algo-3', 'static-key-0', 'static-key-1',
        'static-key-2', 'static-key-3', 'static-sta-private-algo',
        'static-sta-private-key', 'static-transmit-key', 'status-autorefresh',
        'stop-bits', 'store-every', 'store-leases-disk', 'streaming-enabled',
        'streaming-max-rate', 'streaming-server', 'supplicant-identity',
        'switch-to-spt-bytes', 'switch-to-spt-interval', 'switch-to-spt',
        'syslog-facility', 'syslog-severity', 'target-scope', 'target',
        'tcp-close-timeout', 'tcp-close-wait-timeout',
        'tcp-established-timeout', 'tcp-fin-wait-timeout',
        'tcp-last-ack-timeout', 'tcp-syn-received-timeout',
        'tcp-syn-sent-timeout', 'tcp-syncookie', 'tcp-time-wait-timeout',
        'term', 'test-id', 'threshold', 'time-zone-name', 'time-zone',
        'timeout-timer', 'timeout', 'tls-certificate', 'tls-mode',
        'to-addresses', 'topics', 'transmit-hold-count', 'transparent-proxy',
        'transport-address', 'trap-generators', 'trap-target', 'trap-version',
        'ttl', 'tunnel', 'type', 'udp-stream-timeout', 'udp-timeout',
        'unicast-ciphers', 'update-stats-interval', 'update-timer',
        'use-compression', 'use-encryption', 'use-explicit-null',
        'use-ip-firewall-for-pppoe', 'use-ip-firewall-for-vlan',
        'use-ip-firewall', 'use-ipv6', 'use-mpls', 'use-peer-dns',
        'use-peer-ntp', 'use-radius', 'use-service-tag', 'use-vj-compression',
        'user', 'v3-protocol', 'valid-lifetime', 'vcno',
        'verify-client-certificate', 'version', 'vlan-id', 'vrid',
        'watch-address', 'watchdog-timer', 'wds-cost-range',
        'wds-default-bridge', 'wds-default-cost', 'wds-ignore-ssid',
        'wds-mode', 'wins-server', 'wmm-support', 'wpa-pre-shared-key',
        'wpa2-pre-shared-key', 'write-access', 'burst-limit',
        'burst-threshold', 'burst-time', 'limit-at', 'priority', 'max-limit',
        'tree', 'packet-mark', 'value', 'option', 'target-addresses', 'queue',
        'encryption-password', 'always-broadcast', 'connect-to',
        'adaptive-noise-immunity', 'compression', 'band', 'country',
        'frequency', 'hw-retries', 'rate-selection', 'scan-list'
    ]
    keyword2_list = [
        'set', 'add', 'delay', 'do', 'error', 'execute', 'find', 'for',
        'foreach', 'global', 'if', 'len', 'local', 'nothing', 'parse', 'pick',
        'put', 'resolve', 'set', 'time', 'toarray', 'tobool', 'toid', 'toip',
        'toip6', 'tonum', 'tostr', 'totime', 'typeof', 'while', 'beep',
        'export', 'import', 'led', 'password', 'ping', 'quit', 'redo', 'setup',
        'undo', 'print', 'detail', 'file', 'log', 'info', 'get', 'warning',
        'critical'
    ]
    keyword3_list = [
        '/', 'aaa', 'accounting', 'address', 'address-list', 'align', 'area',
        'bandwidth-server', 'bfd', 'bgp', 'bridge', 'client', 'clock',
        'community', 'config', 'connection', 'console', 'customer', 'default',
        'dhcp-client', 'dhcp-server', 'discovery', 'dns', 'e-mail', 'ethernet',
        'filter', 'firewall', 'firmware', 'gps', 'graphing', 'group',
        'hardware', 'health', 'hotspot', 'identity', 'igmp-proxy', 'incoming',
        'instance', 'interface0', 'ip', 'ipsec', 'ipv6', 'irq', 'l2tp-server',
        'lcd', 'ldp', 'logging', 'mac-server', 'mac-winbox', 'mangle',
        'manual', 'mirror', 'mme', 'mpls', 'nat', 'nd', 'neighbor', 'network',
        'note', 'ntp', 'ospf', 'ospf-v3', 'ovpn-server', 'page', 'peer', 'pim',
        'ping', 'policy', 'pool', 'port', 'ppp', 'pppoe-client', 'pptp-server',
        'prefix', 'profile', 'proposal', 'proxy', 'queue', 'radius',
        'resource', 'rip', 'ripng', 'route', 'routing', 'screen', 'script',
        'security-profiles', 'server', 'service', 'service-port', 'settings',
        'shares', 'smb', 'sms', 'sniffer', 'snmp', 'snooper', 'socks',
        'sstp-server', 'system', 'tool', 'tracking', 'traffic-flow',
        'traffic-generator', 'type', 'upgrade', 'upnp', 'user', 'user-manager',
        'users', 'vlan', 'vrrp', 'watchdog', 'web-access', 'wireless', 'pptp',
        'pppoe', 'lan', 'wan', 'layer7-protocol', 'eth-', 'wlan-', 'bridge-'
    ]

    splitter = re.compile(r"(\{\.|\.\}|\#|\'|\"\"\"|\n|\s+|\w+|\W)")
    #Characters that autoindent one level on pressing Return/Enter
    autoindent_characters = [":", "="]

    def __init__(self, parent=None):
        """Overridden initialization"""
        #Initialize superclass
        super().__init__()
        #Set the default style values
        self.setDefaultColor(self.default_color)
        self.setDefaultPaper(self.default_paper)
        self.setDefaultFont(self.default_font)
        #Reset autoindentation style
        self.setAutoIndentStyle(0)
        #Set the theme
        self.set_theme(data.theme)

    def language(self):
        return "RouterOS"

    def description(self, style):
        if style < len(self.styles):
            description = "Custom lexer for the RouterOS syntax by MikroTik"
        else:
            description = ""
        return description

    def set_theme(self, theme):
        for style in self.styles:
            # Papers
            self.setPaper(data.QColor(theme.Paper.RouterOS.Default),
                          self.styles[style])
            # Fonts
            lexers.set_font(self, style, getattr(theme.Font.RouterOS, style))

    def styleText(self, start, end):
        """
        Overloaded method for styling text.
        NOTE:
            Very slow if done in Python!
            Using the Cython version is better.
            The fastest would probably be adding the lexer directly into
            the QScintilla source. Maybe never :-)
        """
        #Style in pure Python, VERY SLOW!
        editor = self.editor()
        if editor is None:
            return
        #Initialize the styling
        self.startStyling(start)
        #Scintilla works with bytes, so we have to adjust the start and end boundaries
        text = bytearray(editor.text().lower(),
                         "utf-8")[start:end].decode("utf-8")
        #Loop optimizations
        setStyling = self.setStyling
        operator_list = self.operator_list
        comment_list = self.comment_list
        keyword1_list = self.keyword1_list
        keyword2_list = self.keyword2_list
        keyword3_list = self.keyword3_list
        DEFAULT = self.styles["Default"]
        OPERATOR = self.styles["Operator"]
        COMMENT = self.styles["Comment"]
        KEYWORD1 = self.styles["Keyword1"]
        KEYWORD2 = self.styles["Keyword2"]
        KEYWORD3 = self.styles["Keyword3"]
        #Initialize various states and split the text into tokens
        commenting = False
        tokens = [(token, len(bytearray(token, "utf-8")))
                  for token in self.splitter.findall(text)]
        #Style the tokens accordingly
        for i, token in enumerate(tokens):
            if commenting == True:
                #Continuation of comment
                setStyling(token[1], COMMENT)
                #Check if comment ends
                if "\n" in token[0]:
                    commenting = False
            elif token[0] in operator_list:
                setStyling(token[1], OPERATOR)
            elif token[0] in comment_list:
                setStyling(token[1], COMMENT)
                commenting = True
            elif token[0] in keyword1_list:
                setStyling(token[1], KEYWORD1)
            elif token[0] in keyword2_list:
                setStyling(token[1], KEYWORD2)
            elif token[0] in keyword3_list:
                setStyling(token[1], KEYWORD3)
            else:
                setStyling(token[1], DEFAULT)
示例#19
0
class CiCode(data.QsciLexerCustom):
    """
    Custom lexer for the Citect CiCode programming language
    """
    class Sequence:
        def __init__(self, 
                     start, 
                     stop_sequences, 
                     stop_characters, 
                     style, 
                     add_to_style):
            self.start = start
            self.stop_sequences = stop_sequences
            self.stop_characters = stop_characters
            self.style = style
            self.add_to_style = add_to_style
    
    styles = {
        "Default" : 0,
        "Comment" : 1,
        "MultilineComment" : 2,
        "Keyword" : 3,
        "BuiltInFunction" : 4,
        "String" : 5,
        "Number" : 6,
        "Operator" : 7,
        "Function" : 8,
    }
    # Class variables
    default_color = data.QColor(data.theme.Font.CiCode.Default[1])
    default_paper = data.QColor(data.theme.Paper.CiCode.Default)
    default_font = data.QFont(data.current_font_name, data.current_font_size)
    keyword_list = [
        "function", "end", "if", "else", "do", "then",
        "while", "for", "mod", "bitand", "bitor", "bitxor",
        "and", "or", "not", "bitand", "bitor", "bitxor",
        "global", "public", "private", "return", 
    ]
    type_list = [
        "string", "object", "int", "real", "quality", "timestamp",
    ]
    builtin_function_list = [
        "abs", "acccontrol", "accumbrowseclose", "accumbrowsefirst", "accumbrowsegetfield", "accumbrowsenext", "accumbrowsenumrecords", 
        "accumbrowseopen", "accumbrowseprev", "alarmack", "alarmackrec", "alarmacktag", "alarmactive", "alarmcatgetformat", 
        "alarmclear", "alarmclearrec", "alarmcleartag", "alarmcomment", "alarmcount", "alarmcountequipment", "alarmcountlist", 
        "alarmdelete", "alarmdisable", "alarmdisablerec", "alarmdisabletag", "alarmdsp", "alarmdspclusteradd", "alarmdspclusterinuse", 
        "alarmdspclusterremove", "alarmdsplast", "alarmdspnext", "alarmdspprev", "alarmenable", "alarmenablerec", "alarmenabletag", 
        "alarmeventque", "alarmfilterclose", "alarmfiltereditappend", "alarmfiltereditclose", "alarmfiltereditcommit", "alarmfiltereditfirst", "alarmfiltereditlast", 
        "alarmfiltereditnext", "alarmfiltereditopen", "alarmfiltereditprev", "alarmfiltereditset", "alarmfilterform", "alarmfilteropen", "alarmfirstcatrec", 
        "alarmfirstprirec", "alarmfirsttagrec", "alarmgetdelay", "alarmgetdelayrec", "alarmgetdsp", "alarmgetfieldrec", "alarmgetfiltername", 
        "alarmgetinfo", "alarmgetorderbykey", "alarmgetthreshold", "alarmgetthresholdrec", "alarmhelp", "alarmnextcatrec", "alarmnextprirec", 
        "alarmnexttagrec", "alarmnotifyvarchange", "alarmqueryfirstrec", "alarmquerynextrec", "alarmresetquery", "alarmsetdelay", "alarmsetdelayrec", 
        "alarmsetinfo", "alarmsetquery", "alarmsetthreshold", "alarmsetthresholdrec", "alarmsplit", "alarmsumappend", "alarmsumcommit", 
        "alarmsumdelete", "alarmsumfind", "alarmsumfirst", "alarmsumget", "alarmsumlast", "alarmsumnext", "alarmsumprev", 
        "alarmsumset", "alarmsumsplit", "alarmsumtype", "almbrowseack", "almbrowseclear", "almbrowseclose", "almbrowsedisable", 
        "almbrowseenable", "almbrowsefirst", "almbrowsegetfield", "almbrowsenext", "almbrowsenumrecords", "almbrowseopen", "almbrowseprev", 
        "almsummaryack", "almsummaryclear", "almsummaryclose", "almsummarycommit", "almsummarydelete", "almsummarydeleteall", "almsummarydisable", 
        "almsummaryenable", "almsummaryfirst", "almsummarygetfield", "almsummarylast", "almsummarynext", "almsummarynumrecords", "almsummaryopen", 
        "almsummaryprev", "almsummarysetfieldvalue", "almtagsack", "almtagsclear", "almtagsclose", "almtagsdisable", "almtagsenable", 
        "almtagsfirst", "almtagsgetfield", "almtagsnext", "almtagsnumrecords", "almtagsopen", "almtagsprev", "anbyname", 
        "arccos", "arcsin", "arctan", "areacheck", "ass", "asschain", "asschainpage", 
        "asschainpopup", "asschainwin", "asschainwinfree", "assgetproperty", "assgetscale", "assinfo", "assinfoex", 
        "asspage", "asspopup", "assscalestr", "asstag", "asstitle", "assvartags", "asswin", 
        "assert", "beep", "callevent", "chainevent", "chartostr", "citectcolourtopackedrgb", "citectinfo", 
        "clipcopy", "clippaste", "clipreadln", "clipsetmode", "clipwriteln", "clusteractivate", "clusterdeactivate", 
        "clusterfirst", "clustergetname", "clusterisactive", "clusternext", "clusterservertypes", "clustersetname", "clusterstatus", 
        "clusterswapactive", "codesetmode", "codetrace", "comclose", "comopen", "comread", "comreset", 
        "comwrite", "cos", "createcontrolobject", "createobject", "ddeexec", "ddepost", "dderead", 
        "ddewrite", "ddehexecute", "ddehgetlasterror", "ddehinitiate", "ddehpoke", "ddehreadln", "ddehrequest", 
        "ddehsetmode", "ddehterminate", "ddehwriteln", "dllcall", "dllcallex", "dllclose", "dllopen", 
        "date", "dateadd", "dateday", "dateinfo", "datemonth", "datesub", "dateweekday", 
        "dateyear", "debugbreak", "debugmsg", "debugmsgset", "degtorad", "delayshutdown", "devappend", 
        "devclose", "devcontrol", "devcurr", "devdelete", "devdisable", "deveof", "devfind", 
        "devfirst", "devflush", "devgetfield", "devhistory", "devinfo", "devmodify", "devnext", 
        "devopen", "devopengrp", "devprev", "devprint", "devread", "devreadln", "devrecno", 
        "devseek", "devsetfield", "devsize", "devwrite", "devwriteln", "devzap", "displayruntimemanager", 
        "dllclasscallmethod", "dllclasscreate", "dllclassdispose", "dllclassgetproperty", "dllclassisvalid", "dllclasssetproperty", "driverinfo", 
        "dspancreatecontrolobject", "dspanfree", "dspangetarea", "dspangetmetadata", "dspangetmetadataat", "dspangetpos", "dspangetprivilege", 
        "dspaninrgn", "dspaninfo", "dspanmove", "dspanmoverel", "dspannew", "dspannewrel", "dspansetmetadata", 
        "dspansetmetadataat", "dspbar", "dspbmp", "dspbutton", "dspbuttonfn", "dspchart", "dspcol", 
        "dspdel", "dspdelayrenderbegin", "dspdelayrenderend", "dspdirty", "dsperror", "dspfile", "dspfilegetinfo", 
        "dspfilegetname", "dspfilescroll", "dspfilesetname", "dspfont", "dspfonthnd", "dspfullscreen", "dspgetanbottom", 
        "dspgetancur", "dspgetanextent", "dspgetanfirst", "dspgetanfrompoint", "dspgetanheight", "dspgetanleft", "dspgetannext", 
        "dspgetanright", "dspgetantop", "dspgetanwidth", "dspgetenv", "dspgetmouse", "dspgetmouseover", "dspgetnearestan", 
        "dspgetparentan", "dspgetslider", "dspgettip", "dspgraybutton", "dspinfo", "dspinfodestroy", "dspinfofield", 
        "dspinfonew", "dspinfovalid", "dspisbuttongray", "dspkernel", "dspmci", "dspmarkermove", "dspmarkernew", 
        "dspplaysound", "dsppopupconfigmenu", "dsppopupmenu", "dsprichtext", "dsprichtextedit", "dsprichtextenable", "dsprichtextgetinfo", 
        "dsprichtextload", "dsprichtextpgscroll", "dsprichtextprint", "dsprichtextsave", "dsprichtextscroll", "dsprubend", "dsprubmove", 
        "dsprubsetclip", "dsprubstart", "dspsetslider", "dspsettip", "dspsettooltipfont", "dspstatus", "dspstr", 
        "dspsym", "dspsymanm", "dspsymanmex", "dspsymatsize", "dsptext", "dsptipmode", "dsptrend", 
        "dsptrendinfo", "dumpkernel", "engtogeneric", "entercriticalsection", "equipbrowseclose", "equipbrowsefirst", "equipbrowsegetfield", 
        "equipbrowsenext", "equipbrowsenumrecords", "equipbrowseopen", "equipbrowseprev", "equipcheckupdate", "equipgetproperty", "equipsetproperty", 
        "equipstatebrowseclose", "equipstatebrowsefirst", "equipstatebrowsegetfield", "equipstatebrowsenext", "equipstatebrowsenumrecords", "equipstatebrowseopen", "equipstatebrowseprev", 
        "errcom", "errdrv", "errgethw", "errhelp", "errinfo", "errlog", "errmsg", 
        "errset", "errsethw", "errsetlevel", "errtrap", "exec", "executedtspkg", "exp", 
        "ftpclose", "ftpfilecopy", "ftpfilefind", "ftpfilefindclose", "ftpopen", "fact", "fileclose", 
        "filecopy", "filedelete", "fileeof", "fileexist", "filefind", "filefindclose", "filegettime", 
        "filemakepath", "fileopen", "fileprint", "fileread", "filereadblock", "filereadln", "filerename", 
        "filerichtextprint", "fileseek", "filesettime", "filesize", "filesplitpath", "filewrite", "filewriteblock", 
        "filewriteln", "fmtclose", "fmtfieldhnd", "fmtgetfield", "fmtgetfieldcount", "fmtgetfieldhnd", "fmtgetfieldname", 
        "fmtgetfieldwidth", "fmtopen", "fmtsetfield", "fmtsetfieldhnd", "fmttostr", "formactive", "formaddlist", 
        "formbutton", "formcheckbox", "formcombobox", "formcurr", "formdestroy", "formedit", "formfield", 
        "formgetcurrinst", "formgetdata", "formgetinst", "formgettext", "formgoto", "formgroupbox", "forminput", 
        "formlistaddtext", "formlistbox", "formlistdeletetext", "formlistselecttext", "formnew", "formnumpad", "formopenfile", 
        "formpassword", "formposition", "formprompt", "formradiobutton", "formread", "formsaveasfile", "formsecurepassword", 
        "formselectprinter", "formsetdata", "formsetinst", "formsettext", "formwndhnd", "fullname", "fuzzyclose", 
        "fuzzygetcodevalue", "fuzzygetshellvalue", "fuzzyopen", "fuzzysetcodevalue", "fuzzysetshellvalue", "fuzzytrace", "getarea", 
        "getbluevalue", "getenv", "getevent", "getgreenvalue", "getlanguage", "getlogging", "getpriv", 
        "getredvalue", "getwintitle", "grpclose", "grpdelete", "grpfirst", "grpin", "grpinsert", 
        "grpmath", "grpname", "grpnext", "grpopen", "grptostr", "halt", "hextostr", 
        "highbyte", "highword", "htmlhelp", "hwalarmque", "iodevicecontrol", "iodeviceinfo", "iodevicestats", 
        "infoform", "infoforman", "input", "inttoreal", "inttostr", "iserror", "kercmd", 
        "kernelqueuelength", "kerneltableinfo", "kerneltableitemcount", "keyallowcursor", "keybs", "keydown", "keyget", 
        "keygetcursor", "keyleft", "keymove", "keypeek", "keyput", "keyputstr", "keyreplay", 
        "keyreplayall", "keyright", "keysetcursor", "keysetseq", "keyup", "languagefiletranslate", "leavecriticalsection", 
        "libalarmfilterform", "ln", "log", "login", "loginform", "logout", "logoutidle", 
        "lowbyte", "lowword", "mailerror", "maillogoff", "maillogon", "mailread", "mailsend", 
        "makecitectcolour", "max", "menugetchild", "menugetfirstchild", "menugetgenericnode", "menugetnextchild", "menugetpagenode", 
        "menugetparent", "menugetprevchild", "menugetwindownode", "menunodeaddchild", "menunodegetproperty", "menunodehascommand", "menunodeisdisabled", 
        "menunodeishidden", "menunoderemove", "menunoderuncommand", "menunodesetdisabledwhen", "menunodesethiddenwhen", "menunodesetproperty", "menureload", 
        "message", "min", "msgbrdcst", "msgclose", "msggetcurr", "msgopen", "msgrpc", 
        "msgread", "msgstate", "msgwrite", "multimonitorstart", "multisignatureform", "multisignaturetagwrite", "name", 
        "oledatetotime", "objectassociateevents", "objectassociatepropertywithtag", "objectbyname", "objecthasinterface", "objectisvalid", "objecttostr", 
        "onevent", "packedrgb", "packedrgbtocitectcolour", "pagealarm", "pageback", "pagedisabled", "pagedisplay", 
        "pageexists", "pagefile", "pagefileinfo", "pageforward", "pagegetint", "pagegetstr", "pagegoto", 
        "pagehardware", "pagehistorydspmenu", "pagehistoryempty", "pagehome", "pageinfo", "pagelast", "pagelistcount", 
        "pagelistcurrent", "pagelistdelete", "pagelistdisplay", "pagelistinfo", "pagemenu", "pagenext", "pagepeekcurrent", 
        "pagepeeklast", "pagepoplast", "pagepopup", "pageprev", "pageprocessanalyst", "pageprocessanalystpens", "pagepushlast", 
        "pagerecall", "pagerichtextfile", "pagesoe", "pageselect", "pagesetint", "pagesetstr", "pagesummary", 
        "pagetask", "pagetransformcoords", "pagetrend", "pagetrendex", "parameterget", "parameterput", "pathtostr", 
        "pi", "plotclose", "plotdraw", "plotfile", "plotgetmarker", "plotgrid", "plotinfo", 
        "plotline", "plotmarker", "plotopen", "plotscalemarker", "plotsetmarker", "plottext", "plotxyline", 
        "pow", "print", "printfont", "println", "processanalystloadfile", "processanalystpopup", "processanalystselect", 
        "processanalystsetpen", "processanalystwin", "processisclient", "processisserver", "processrestart", "productinfo", "projectinfo", 
        "projectrestartget", "projectrestartset", "projectset", "prompt", "pulse", "qualitycreate", "qualitygetpart", 
        "qualityisbad", "qualityiscontrolinhibit", "qualityisgood", "qualityisoverride", "qualityisuncertain", "qualitysetpart", "qualitytostr", 
        "queclose", "quelength", "queopen", "quepeek", "queread", "quewrite", "radtodeg", 
        "rand", "reread", "realtostr", "repgetcluster", "repgetcontrol", "repsetcontrol", "report", 
        "round", "soearchive", "soedismount", "soeeventadd", "soemount", "spcalarms", "spcclientinfo", 
        "spcgethistogramtable", "spcgetsubgrouptable", "spcplot", "spcprocessxrsget", "spcprocessxrsset", "spcsetlimit", "spcspeclimitget", 
        "spcspeclimitset", "spcsubgroupsizeget", "spcsubgroupsizeset", "sqlappend", "sqlbegintran", "sqlcall", "sqlcancel", 
        "sqlclose", "sqlcommit", "sqlconnect", "sqlcreate", "sqldisconnect", "sqldispose", "sqlend", 
        "sqlerrmsg", "sqlexec", "sqlfieldinfo", "sqlgetfield", "sqlgetrecordset", "sqlgetscalar", "sqlinfo", 
        "sqlisnullfield", "sqlnext", "sqlnofields", "sqlnumchange", "sqlnumfields", "sqlopen", "sqlparamsclearall", 
        "sqlparamssetasint", "sqlparamssetasreal", "sqlparamssetasstring", "sqlprev", "sqlquerycreate", "sqlquerydispose", "sqlrollback", 
        "sqlrowcount", "sqlset", "sqltraceoff", "sqltraceon", "schdclose", "schdconfigclose", "schdconfigfirst", 
        "schdconfiggetfield", "schdconfignext", "schdconfignumrecords", "schdconfigopen", "schdconfigprev", "schdfirst", "schdnext", 
        "schdnumrecords", "schdopen", "schdprev", "schdspecialadd", "schdspecialclose", "schdspecialdelete", "schdspecialfirst", 
        "schdspecialgetfield", "schdspecialitemadd", "schdspecialitemclose", "schdspecialitemdelete", "schdspecialitemfirst", "schdspecialitemgetfield", "schdspecialitemmodify", 
        "schdspecialitemnext", "schdspecialitemnumrecords", "schdspecialitemopen", "schdspecialitemprev", "schdspecialmodify", "schdspecialnext", "schdspecialnumrecords", 
        "schdspecialopen", "schdspecialprev", "scheduleitemadd", "scheduleitemdelete", "scheduleitemmodify", "scheduleitemsetrepeat", "semclose", 
        "semopen", "semsignal", "semwait", "sendkeys", "serialkey", "serverbrowseclose", "serverbrowsefirst", 
        "serverbrowsegetfield", "serverbrowsenext", "serverbrowsenumrecords", "serverbrowseopen", "serverbrowseprev", "serverdumpkernel", "servergetproperty", 
        "serverinfo", "serverinfoex", "serverisonline", "serverrpc", "serverreload", "serverrestart", "servicegetlist", 
        "setarea", "setevent", "setlanguage", "setlogging", "shutdown", "shutdownform", "shutdownmode", 
        "sign", "sin", "sleep", "sleepms", "sqrt", "strcalcwidth", "strclean", 
        "strfill", "strformat", "strgetchar", "strleft", "strlength", "strlower", "strmid", 
        "strpad", "strright", "strsearch", "strsetchar", "strtochar", "strtodate", "strtofmt", 
        "strtogrp", "strtohex", "strtoint", "strtolines", "strtolocaltext", "strtoperiod", "strtoreal", 
        "strtotime", "strtotimestamp", "strtovalue", "strtrim", "strtruncfont", "strtruncfonthnd", "strupper", 
        "strword", "subscriptionaddcallback", "subscriptiongetattribute", "subscriptiongetinfo", "subscriptiongetquality", "subscriptiongettag", "subscriptiongettimestamp", 
        "subscriptiongetvalue", "subscriptionremovecallback", "switchconfig", "systime", "systimedelta", "tablelookup", "tablemath", 
        "tableshift", "tagbrowseclose", "tagbrowsefirst", "tagbrowsegetfield", "tagbrowsenext", "tagbrowsenumrecords", "tagbrowseopen", 
        "tagbrowseprev", "tagdebug", "tagdebugform", "tageventformat", "tageventqueue", "taggetproperty", "taggetscale", 
        "taginfo", "taginfoex", "tagrdbreload", "tagramp", "tagread", "tagreadex", "tagresolve", 
        "tagscalestr", "tagsetoverridebad", "tagsetoverridegood", "tagsetoverridequality", "tagsetoverrideuncertain", "tagsubscribe", "tagunresolve", 
        "tagunsubscribe", "tagwrite", "tagwriteeventque", "tagwriteintarray", "tagwriterealarray", "tan", "taskcluster", 
        "taskgetsignal", "taskhnd", "taskkill", "tasknew", "tasknewex", "taskresume", "tasksetsignal", 
        "tasksuspend", "testrandomwave", "testsawwave", "testsinwave", "testsquarewave", "testtriangwave", "time", 
        "timecurrent", "timehour", "timeinfo", "timeinttotimestamp", "timemidnight", "timemin", "timesec", 
        "timeset", "timetostr", "timeutcoffset", "timestampadd", "timestampcreate", "timestampcurrent", "timestampdifference", 
        "timestampformat", "timestampgetpart", "timestampsub", "timestamptostr", "timestamptotimeint", "toggle", "tracemsg", 
        "trenddspcursorcomment", "trenddspcursorscale", "trenddspcursortag", "trenddspcursortime", "trenddspcursorvalue", "trendgetan", "trendpopup", 
        "trendrun", "trendsetdate", "trendsetscale", "trendsetspan", "trendsettime", "trendsettimebase", "trendwin", 
        "trendzoom", "trnaddhistory", "trnbrowseclose", "trnbrowsefirst", "trnbrowsegetfield", "trnbrowsenext", "trnbrowsenumrecords", 
        "trnbrowseopen", "trnbrowseprev", "trnclientinfo", "trncompareplot", "trndelhistory", "trndelete", "trnecho", 
        "trneventgettable", "trneventgettablems", "trneventsettable", "trneventsettablems", "trnexportcsv", "trnexportclip", "trnexportdbf", 
        "trnexportdde", "trnflush", "trngetbufevent", "trngetbuftime", "trngetbufvalue", "trngetcluster", "trngetcursorevent", 
        "trngetcursormstime", "trngetcursorpos", "trngetcursortime", "trngetcursorvalue", "trngetcursorvaluestr", "trngetdefscale", "trngetdisplaymode", 
        "trngetevent", "trngetformat", "trngetgatedvalue", "trngetinvalidvalue", "trngetmstime", "trngetmode", "trngetpen", 
        "trngetpencomment", "trngetpenfocus", "trngetpenno", "trngetperiod", "trngetscale", "trngetscalestr", "trngetspan", 
        "trngettable", "trngettime", "trngetunits", "trninfo", "trnisvalidvalue", "trnnew", "trnplot", 
        "trnprint", "trnsamplesconfigured", "trnscroll", "trnselect", "trnsetcursor", "trnsetcursorpos", "trnsetdisplaymode", 
        "trnsetevent", "trnsetpen", "trnsetpenfocus", "trnsetperiod", "trnsetscale", "trnsetspan", "trnsettable", 
        "trnsettime", "usercreate", "usercreateform", "userdelete", "usereditform", "userinfo", "userlogin", 
        "userpassword", "userpasswordexpirydays", "userpasswordform", "usersetstr", "userupdaterecord", "userverify", "variablequality", 
        "variabletimestamp", "verifyprivilegeform", "verifyprivilegetagwrite", "version", "whoami", "wincopy", "winfile", 
        "winfree", "wingetfocus", "wingetwndhnd", "wingoto", "winmode", "winmove", "winnew", 
        "winnewat", "winnext", "winnumber", "winpos", "winprev", "winprint", "winprintfile", 
        "winselect", "winsetname", "winsize", "winstyle", "wintitle", "wndfind", "wndgetfileprofile", 
        "wndgetprofile", "wndhelp", "wndinfo", "wndmonitorinfo", "wndputfileprofile", "wndputprofile", "wndshow", 
        "wndviewer", "xmlclose", "xmlcreate", "xmlgetattribute", "xmlgetattributecount", "xmlgetattributename", "xmlgetattributevalue", 
        "xmlgetchild", "xmlgetchildcount", "xmlgetparent", "xmlgetroot", "xmlnodeaddchild", "xmlnodefind", "xmlnodegetname", 
        "xmlnodegetvalue", "xmlnoderemove", "xmlnodesetvalue", "xmlopen", "xmlsave", "xmlsetattribute", "_objectcallmethod", 
        "_objectgetproperty", "_objectsetproperty", 
    ]
    operator_list = [
        "=", "+", "-", "*", "/", "<", ">", "@", "$", ".",
        "~", "&", "%", "|", "!", "?", "^", ".", ":", "\"",
    ]
    func = Sequence('function', [], ['(', '\n'], styles["Function"], False)
    strseq = Sequence('"', ['"', '\n'], [], styles["String"], True)
    comment = Sequence('//', [], ['\n'], styles["Comment"], True)
    mcomment = Sequence('/*', ['*/'], [], styles["MultilineComment"], True)
    sequence_lists = [strseq, comment, mcomment, func]
    multiline_sequence_list = [mcomment]
    sequence_start_chrs = [x.start for x in sequence_lists]
#    splitter = re.compile(r"(/\*|\*/|\\\"|\(\*|\*\)|//|\n|\"+|\'+|\#+|\s+|\w+|\W)")
    splitter = re.compile(r"(/\*|\*/|\(\*|\*\)|//|\n|\"+|\'+|\#+|\s+|\w+|\W)")
    # Characters that autoindent one level on pressing Return/Enter
    autoindent_characters = ["then", "do", ")"]

    def __init__(self, parent=None):
        """
        Overridden initialization
        """
        # Initialize superclass
        super().__init__()
        # Set the default style values
        self.setDefaultColor(self.default_color)
        self.setDefaultPaper(self.default_paper)
        self.setDefaultFont(self.default_font)
        # Reset autoindentation style
        self.setAutoIndentStyle(0)
        # Set the theme
        self.set_theme(data.theme)
    
    def language(self):
        return "CiCode"
    
    def description(self, style):
        if style < len(self.styles):
            description = "Custom lexer for the CiCode programming languages"
        else:
            description = ""
        return description
    
    def defaultStyle(self):
        return self.styles["Default"]
    
    def braceStyle(self):
        return self.styles["Default"]
    
    def defaultFont(self, style):
        return data.QFont(data.current_font_name, data.current_font_size)
    
    def set_theme(self, theme):
        for style in self.styles:
            # Papers
            self.setPaper(
                data.QColor(theme.Paper.CiCode.Default), 
                self.styles[style]
            )
            # Fonts
            lexers.set_font(self, style, getattr(theme.Font.CiCode, style))
    
    def styleText(self, start, end):
        """
        Overloaded method for styling text.
        """
        # Style in pure Python, VERY SLOW!
        editor = self.editor()
        if editor is None:
            return
        # Initialize the styling
        self.startStyling(start)
        # Scintilla works with bytes, so we have to adjust
        # the start and end boundaries
        text = bytearray(editor.text().lower(), "utf-8")[start:end].decode("utf-8")
        # Loop optimizations
        setStyling      = self.setStyling
        DEFAULT         = self.styles["Default"]
        COMMENT         = self.styles["Comment"]
        KEYWORD         = self.styles["Keyword"]
        BUILTINFUNCTION = self.styles["BuiltInFunction"]
        STRING          = self.styles["String"]
        NUMBER          = self.styles["Number"]
        OPERATOR        = self.styles["Operator"]
        # Initialize various states and split the text into tokens
        stringing = False
        commenting = False
        multiline_commenting = False
        sequence = None
        tokens = [
            (token.lower(), len(bytearray(token, "utf-8"))) 
                for token in self.splitter.findall(text)
        ]
        
        # Check if there is a style(comment, string, ...) stretching on from the previous line
        if start != 0:
            previous_style = editor.SendScintilla(editor.SCI_GETSTYLEAT, start - 1)
            for i in self.multiline_sequence_list:
                if previous_style == i.style:
                    sequence = i
                    break
        
        # Style the tokens accordingly
        for i, token in enumerate(tokens):
            token_name = token[0]
            token_length = token[1]
            if sequence != None:
                if token_name in sequence.stop_sequences:
                    if sequence.add_to_style == True:
                        setStyling(token_length, sequence.style)
                    else:
                        setStyling(token_length, self.styles["Default"])
                    sequence = None
                elif any(ch in token_name for ch in sequence.stop_characters):
                    if sequence.add_to_style == True:
                        setStyling(token_length, sequence.style)
                    else:
                        setStyling(token_length, self.styles["Default"])
                    sequence = None
                else:
                    setStyling(token_length, sequence.style)
            elif token_name in self.sequence_start_chrs:
                for i in self.sequence_lists:
                    if token_name == i.start:
                        if i.stop_sequences == [] and i.stop_characters == []:
                            # Skip styling if both stop sequences and stop characters are empty
                            setStyling(token_length, i.style)
                        else:
                            # Style the sequence and store the reference to it
                            sequence = i
                            if i.add_to_style == True:
                                setStyling(token_length, sequence.style)
                            else:
                                if token_name in self.keyword_list:
                                    setStyling(token_length, KEYWORD)
                                elif token_name in self.type_list:
                                    setStyling(token_length, KEYWORD)
                                elif token_name in self.operator_list:
                                    setStyling(token_length, OPERATOR)
                                elif token_name[0].isdigit():
                                    setStyling(token_length, NUMBER)
                                elif token_name in self.builtin_function_list:
                                    setStyling(token_length, BUILTINFUNCTION)
                                else:
                                    setStyling(token_length, self.styles["Default"])
                        break
            elif token_name in self.keyword_list:
                setStyling(token_length, KEYWORD)
            elif token_name in self.type_list:
                setStyling(token_length, KEYWORD)
            elif token_name in self.operator_list:
                setStyling(token_length, OPERATOR)
            elif token_name[0].isdigit():
                setStyling(token_length, NUMBER)
            elif token_name in self.builtin_function_list:
                setStyling(token_length, BUILTINFUNCTION)
            else:
                setStyling(token_length, DEFAULT)
示例#20
0
    def draw_line_hexagon_no_double_paint(
            self,
            position,
            line_width,
            line_color,
            paint_enabled=[True, True, True, True, True, True],
            shadow=False):
        qpainter = self.painter

        if line_width == 0:
            return

        pen = data.QPen(data.Qt.SolidLine)
        pen.setCapStyle(data.Qt.RoundCap)
        pen.setJoinStyle(data.Qt.RoundJoin)
        pen.setWidth(line_width)
        pen.setColor(line_color)
        qpainter.setPen(pen)
        hex_points = list(
            HexBuilder.generate_hexagon_points(self.edge_length, position))
        x_correction = self.edge_length / 2
        y_correction = self.edge_length / (2 * math.tan(math.radians(30)))
        hex_points = [(x - x_correction, y - y_correction)
                      for x, y in hex_points]
        hex_lines = []

        def line_test(in_line):
            DIFF = 3
            line = in_line
            reversed_line = (line[1], line[0])
            x1, y1 = line[0]
            x2, y2 = line[1]
            xr1, yr1 = reversed_line[0]
            xr2, yr2 = reversed_line[1]
            for l in self.stored_lines:
                xl1, yl1 = l[0]
                xl2, yl2 = l[1]
                if (abs(xl1 - x1) < DIFF and abs(yl1 - y1) < DIFF
                        and abs(xl2 - x2) < DIFF and abs(yl2 - y2) < DIFF):
                    if not (line in self.stored_lines):
                        self.stored_lines.append(line)
                        #self.stored_lines.append(reversed_line)
                    return False
                elif (abs(xl1 - xr1) < DIFF and abs(yl1 - yr1) < DIFF
                      and abs(xl2 - xr2) < DIFF and abs(yl2 - yr2) < DIFF):
                    if not (reversed_line in self.stored_lines):
                        self.stored_lines.append(line)
                        #self.stored_lines.append(reversed_line)
                    return False
            else:
                self.stored_lines.append(line)
                self.stored_lines.append(reversed_line)
                return True

        for i in range(len(hex_points)):
            if paint_enabled[i] == False:
                continue
            n = i + 1
            if n > (len(hex_points) - 1):
                n = 0
            if line_test((hex_points[i], hex_points[n])) == True:
                hex_lines.append(
                    data.QLine(data.QPoint(*hex_points[i]),
                               data.QPoint(*hex_points[n])))
        if hex_lines:
            if shadow == True:
                shadow_0_color = data.QColor(line_color)
                shadow_0_color.setAlpha(64)
                shadow_1_color = data.QColor(line_color)
                shadow_1_color.setAlpha(128)

                pen.setWidth(line_width * 2.0)
                pen.setColor(shadow_0_color)
                qpainter.setPen(pen)
                qpainter.drawLines(*hex_lines)
                pen.setWidth(line_width * 1.5)
                pen.setColor(shadow_1_color)
                qpainter.setPen(pen)
                qpainter.drawLines(*hex_lines)
                pen.setWidth(line_width)
                pen.setColor(line_color)
                qpainter.setPen(pen)
                qpainter.drawLines(*hex_lines)
            else:
                qpainter.drawLines(*hex_lines)
示例#21
0
文件: awk.py 项目: Mr-ZBin/ExCo
class AWK(data.QsciLexerCustom):
    """
    Custom lexer for the AWK programming languages
    """
    styles = {
        "Default": 0,
        "Comment": 1,
        "Keyword": 2,
        "BuiltInVariable": 3,
        "BuiltInFunction": 4,
        "String": 5,
        "Number": 6,
        "Operator": 7,
    }
    # Class variables
    default_color = data.QColor(data.theme.Font.AWK.Default[1])
    default_paper = data.QColor(data.theme.Paper.AWK.Default)
    default_font = data.QFont(data.current_font_name, data.current_font_size)
    keyword_list = [
        "BEGIN",
        "delete",
        "for",
        "in",
        "printf",
        "END",
        "do",
        "function",
        "next",
        "return",
        "break",
        "else",
        "getline",
        "print",
        "while",
        "continue",
        "exit",
        "if",
    ]
    builtin_variable_list = [
        "ARGC",
        "ARGV",
        "CONVFMT",
        "ENVIRON",
        "FILENAME",
        "FNR",
        "FS",
        "NF",
        "NR",
        "OFMT",
        "OFS",
        "ORS",
        "RLENGTH",
        "RS",
        "RSTART",
        "SUBSEP",
    ]
    builtin_function_list = [
        "atan2",
        "index",
        "match",
        "sprintf",
        "substr",
        "close",
        "int",
        "rand",
        "sqrt",
        "system",
        "cos",
        "length",
        "sin",
        "srand",
        "tolower",
        "exp",
        "log",
        "split",
        "sub",
        "toupper",
        "gsub",
    ]
    operator_list = [
        "=",
        "+",
        "-",
        "*",
        "/",
        "<",
        ">",
        "@",
        "$",
        ".",
        "~",
        "&",
        "%",
        "|",
        "!",
        "?",
        "^",
        ".",
        ":",
        "\"",
    ]
    splitter = re.compile(r"(\{\.|\.\}|\#|\'|\"\"\"|\n|\s+|\w+|\W)")
    # Characters that autoindent one level on pressing Return/Enter
    autoindent_characters = ["{"]

    def __init__(self, parent=None):
        """
        Overridden initialization
        """
        # Initialize superclass
        super().__init__()
        # Set the default style values
        self.setDefaultColor(self.default_color)
        self.setDefaultPaper(self.default_paper)
        self.setDefaultFont(self.default_font)
        # Reset autoindentation style
        self.setAutoIndentStyle(0)
        # Set the theme
        self.set_theme(data.theme)

    def language(self):
        return "AWK"

    def description(self, style):
        if style < len(self.styles):
            description = "Custom lexer for the AWK programming languages"
        else:
            description = ""
        return description

    def defaultStyle(self):
        return self.styles["Default"]

    def braceStyle(self):
        return self.styles["Default"]

    def defaultFont(self, style):
        return data.QFont(data.current_font_name, data.current_font_size)

    def set_theme(self, theme):
        for style in self.styles:
            # Papers
            self.setPaper(data.QColor(theme.Paper.AWK.Default),
                          self.styles[style])
            # Fonts
            lexers.set_font(self, style, getattr(theme.Font.AWK, style))

    def styleText(self, start, end):
        """
        Overloaded method for styling text.
        """
        # Style in pure Python, VERY SLOW!
        editor = self.editor()
        if editor is None:
            return
        # Initialize the styling
        self.startStyling(start)
        # Scintilla works with bytes, so we have to adjust
        # the start and end boundaries
        text = bytearray(editor.text(), "utf-8")[start:end].decode("utf-8")
        # Loop optimizations
        setStyling = self.setStyling
        operator_list = self.operator_list
        builtin_variable_list = self.builtin_variable_list
        builtin_function_list = self.builtin_function_list
        keyword_list = self.keyword_list
        DEFAULT = self.styles["Default"]
        COMMENT = self.styles["Comment"]
        KEYWORD = self.styles["Keyword"]
        BUILTINVARIABLE = self.styles["BuiltInVariable"]
        BUILTINFUNCTION = self.styles["BuiltInFunction"]
        STRING = self.styles["String"]
        NUMBER = self.styles["Number"]
        OPERATOR = self.styles["Operator"]
        # Initialize various states and split the text into tokens
        stringing = False
        commenting = False
        tokens = [(token, len(bytearray(token, "utf-8")))
                  for token in self.splitter.findall(text)]
        # Style the tokens accordingly
        for i, token in enumerate(tokens):
            if commenting == True:
                # Continuation of comment
                setStyling(token[1], COMMENT)
                # Check if comment ends
                if "\n" in token[0]:
                    commenting = False
            elif stringing == True:
                # Continuation of a string
                setStyling(token[1], STRING)
                # Check if string ends
                if (token[0] == "\"" and (tokens[i - 1][0] != "\\")
                        or "\n" in token[0]):
                    stringing = False
            elif token[0] == "#":
                setStyling(token[1], COMMENT)
                commenting = True
            elif token[0] == "\"":
                # Start of a string
                setStyling(token[1], STRING)
                stringing = True
            elif token[0] in operator_list:
                setStyling(token[1], OPERATOR)
            elif token[0] in keyword_list:
                setStyling(token[1], KEYWORD)
            elif token[0] in builtin_variable_list:
                setStyling(token[1], BUILTINVARIABLE)
            elif token[0] in builtin_function_list:
                setStyling(token[1], BUILTINFUNCTION)
            else:
                setStyling(token[1], DEFAULT)
示例#22
0
class Ada(data.QsciLexerCustom):
    """Custom lexer for the Ada programming languages"""
    styles = {
        "Default": 0,
        "Comment": 1,
        "Keyword": 2,
        "String": 3,
        "Procedure": 4,
        "Number": 5,
        "Type": 6,
        "Package": 7
    }

    #Class variables
    default_color = data.QColor(data.theme.Font.Ada.Default[1])
    default_paper = data.QColor(data.theme.Paper.Ada.Default)
    default_font = data.QFont(data.current_font_name, data.current_font_size)
    keyword_list = [
        "abort",
        "else",
        "new",
        "return",
        "abs",
        "elsif",
        "not",
        "reverse",
        "abstract",
        "end",
        "null",
        "accept",
        "entry",
        "select",
        "access",
        "exception",
        "of",
        "separate",
        "aliased",
        "exit",
        "or",
        "some",
        "all",
        "others",
        "subtype",
        "and",
        "for",
        "out",
        "synchronized",
        "array",
        "function",
        "overriding",
        "at",
        "tagged",
        "generic",
        "package",
        "task",
        "begin",
        "goto",
        "pragma",
        "terminate",
        "body",
        "private",
        "then",
        "if",
        "procedure",
        "type",
        "case",
        "in",
        "protected",
        "constant",
        "interface",
        "until",
        "is",
        "raise",
        "use",
        "declare",
        "range",
        "delay",
        "limited",
        "record",
        "when",
        "delta",
        "loop",
        "rem",
        "while",
        "digits",
        "renames",
        "with",
        "do",
        "mod",
        "requeue",
        "xor",
    ]
    splitter = re.compile(r"(\-\-|\s+|\w+|\W)")

    def __init__(self, parent=None):
        """Overridden initialization"""
        #Initialize superclass
        super().__init__()
        #Set the default style values
        self.setDefaultColor(self.default_color)
        self.setDefaultPaper(self.default_paper)
        self.setDefaultFont(self.default_font)
        #Reset autoindentation style
        self.setAutoIndentStyle(0)
        #Set the theme
        self.set_theme(data.theme)

    def language(self):
        return "Ada"

    def description(self, style):
        if style <= 7:
            description = "Custom lexer for the Ada programming languages"
        else:
            description = ""
        return description

    def set_theme(self, theme):
        for style in self.styles:
            # Papers
            self.setPaper(data.QColor(theme.Paper.Ada.Default),
                          self.styles[style])
            # Fonts
            lexers.set_font(self, style, getattr(theme.Font.Ada, style))

    def styleText(self, start, end):
        """
        Overloaded method for styling text.
        NOTE:
            Very slow if done in Python!
            Using the Cython version is better.
            The fastest would probably be adding the lexer directly into
            the QScintilla source. Maybe never :-)
        """
        #Get the global cython flag
        if lexers.cython_lexers_found == True:
            #Cython module found
            lexers.cython_lexers.style_ada(start, end, self, self.editor())
        else:
            #Style in pure Python, VERY SLOW!
            editor = self.editor()
            if editor is None:
                return
            #Initialize the procedure/package counter
            pp_counter = []
            #Initialize the styling
            self.startStyling(0)
            #Scintilla works with bytes, so we have to adjust the start and end boundaries
            text = bytearray(editor.text().lower(), "utf-8").decode("utf-8")
            #Loop optimizations
            setStyling = self.setStyling
            kw_list = self.keyword_list
            DEF = self.styles["Default"]
            KWD = self.styles["Keyword"]
            COM = self.styles["Comment"]
            STR = self.styles["String"]
            PRO = self.styles["Procedure"]
            NUM = self.styles["Number"]
            PAC = self.styles["Package"]
            #            TYP = self.styles["Type"]
            #Initialize comment state and split the text into tokens
            commenting = False
            stringing = False
            tokens = [(token, len(bytearray(token, "utf-8")))
                      for token in self.splitter.findall(text)]
            #Style the tokens accordingly
            for i, token in enumerate(tokens):
                if commenting == True:
                    #Continuation of comment
                    setStyling(token[1], COM)
                    #Check if comment ends
                    if "\n" in token[0]:
                        commenting = False
                elif stringing == True:
                    #Continuation of a string
                    setStyling(token[1], STR)
                    #Check if string ends
                    if token[0] == "\"" or "\n" in token[0]:
                        stringing = False
                elif token[0] == "\"":
                    #Start of a string
                    setStyling(token[1], STR)
                    stringing = True
                elif token[0] in kw_list:
                    #Keyword
                    setStyling(token[1], KWD)
                elif token[0] == "--":
                    #Start of a comment
                    setStyling(token[1], COM)
                    commenting = True
                elif i > 1 and tokens[i - 2][0] == "procedure":
                    #Procedure name
                    setStyling(token[1], PRO)
                    #Mark the procedure
                    if tokens[i + 1][0] != ";":
                        pp_counter.append("PROCEDURE")
                elif i > 1 and (tokens[i - 2][0] == "package"
                                or tokens[i - 2][0] == "body"):
                    #Package name
                    setStyling(token[1], PAC)
                    #Mark the package
                    pp_counter.append("PACKAGE")
                elif (i > 1 and tokens[i - 2][0]
                      == "end") and (len(tokens) - 1 >= i + 1):
                    #Package or procedure name end
                    if len(pp_counter) > 0:
                        if pp_counter.pop() == "PACKAGE":
                            setStyling(token[1], PAC)
                        else:
                            setStyling(token[1], PRO)
                    else:
                        setStyling(token[1], DEF)
                elif functions.is_number(token[0]):
                    #Number
                    setStyling(token[1], NUM)
                else:
                    setStyling(token[1], DEF)
示例#23
0
    def create_background_image(in_scale=1.0):
        """
        Dinamically create the settings manipulator's background image
        """
        # Check if the QPixmap has been created already
        if SettingsGuiManipulator.settings_background_image == None:
            scale = in_scale
            edge_length = 27
            scaled_edge_diff = (edge_length -
                                (edge_length * scale)) / edge_length
            back_color = data.theme.Settings_Background
            edge_color = data.QColor(data.theme.Settings_Hex_Edge)

            SettingsGuiManipulator.theme_name = data.theme.name

            def add_offset(offset):
                x_add = 64.0
                y_add = 20.0
                return (offset[0] + x_add, offset[1] + y_add)

            settings_background_image = data.QImage(
                functions.create_size(*SettingsGuiManipulator.DEFAULT_SIZE),
                data.QImage.Format_ARGB32_Premultiplied)
            settings_background_image.fill(data.Qt.transparent)
            #            settings_background_image.fill(data.QColor(255,255,255))
            qpainter = data.QPainter(settings_background_image)
            qpainter.setRenderHints(data.QPainter.Antialiasing
                                    | data.QPainter.TextAntialiasing
                                    | data.QPainter.SmoothPixmapTransform)

            # Corner options
            x = edge_length + 205
            y = 1.8 * edge_length + 30
            offset = (x, y)
            hb = components.HexBuilder(
                qpainter,
                offset,
                edge_length,
                scale,
                fill_color=back_color,
                line_width=2,
                line_color=edge_color,
            )
            grid_list = [
                (3, True),
                (4, True),
                (4, True),
                (4, True),
                (5, True),
                (1, True),
            ]
            hb.create_grid(*grid_list)
            # Label field
            last_step = hb.get_last_position()
            hb = components.HexBuilder(
                qpainter,
                offset,
                edge_length,
                scale,
                fill_color=data.theme.Settings_Label_Background,
                line_width=3,
                line_color=data.QColor(146, 146, 146),
            )
            hb.set_first_position(last_step)
            hb.create_grid(5, 5, 0, 2, 0, 2, 3, 1, 0, 2, 3, 4)

            # Editor buttons
            offset = (90, 280)
            offset = add_offset(offset)
            row_length = 6
            editor_button_count = 30
            hb = components.HexBuilder(
                qpainter,
                offset,
                edge_length,
                scale,
                fill_color=back_color,
                line_width=2,
                line_color=edge_color,
            )
            grid_list = hb.generate_square_grid_list(row_length,
                                                     editor_button_count)
            hb.create_grid(*grid_list)
            # Editor edge
            hb.next_step_move(3)
            first_edge_hex_position = hb.get_last_position()
            hb = components.HexBuilder(
                qpainter,
                first_edge_hex_position,
                edge_length,
                scale,
                fill_color=back_color,
                line_width=2,
                line_color=edge_color,
            )
            grid_list = [
                (4, True),
                (5, True),
                (4, True),
                (5, True),
                (4, True),
                (5, True),
                (0, True),
                (0, True),
                (0, True),
                (0, True),
                (0, True),
                (1, True),
                (1, True),
                (2, True),
                (1, True),
                (2, True),
                (1, True),
                (2, True),
                (3, True),
                (3, True),
                (3, True),
                (3, True),
                (3, True),
            ]
            hb.create_grid(*grid_list)

            # General buttons
            offset = (offset[0] + (8 * hb.horizontal_step),
                      offset[1] - (6 * hb.vertical_step))
            row_length = 7
            general_button_count = 56
            hb = components.HexBuilder(
                qpainter,
                offset,
                edge_length,
                scale,
                fill_color=back_color,
                line_width=2,
                line_color=edge_color,
            )
            grid_list = hb.generate_square_grid_list(row_length,
                                                     general_button_count)
            hb.create_grid(*grid_list)
            # General edge
            hb.next_step_move(3)
            first_edge_hex_position = hb.get_last_position()
            hb = components.HexBuilder(
                qpainter,
                first_edge_hex_position,
                edge_length,
                scale,
                fill_color=back_color,
                line_width=2,
                line_color=edge_color,
            )
            grid_list = [
                (1, True),
                (2, True),
                (1, True),
                (2, True),
                (1, True),
                (2, True),
                (1, True),
                (0, True),
                (0, True),
                (0, True),
                (0, True),
                (0, True),
                (0, True),
                (0, True),
                (0, True),
                (5, True),
                (5, True),
                (4, True),
                (5, True),
                (4, True),
                (5, True),
                (4, True),
                (4, True),
                (3, True),
                (3, True),
                (3, True),
                (3, True),
                (3, True),
                (3, True),
                (3, True),
                (3, True),
            ]
            hb.create_grid(*grid_list)

            qpainter.end()
            SettingsGuiManipulator.settings_background_image = data.QPixmap.fromImage(
                settings_background_image)
        return SettingsGuiManipulator.settings_background_image
示例#24
0
class CustomPython(data.QsciLexerCustom):
    class Sequence:
        def __init__(self, start, stop_sequences, stop_characters, style,
                     add_to_style):
            self.start = start
            self.stop_sequences = stop_sequences
            self.stop_characters = stop_characters
            self.style = style
            self.add_to_style = add_to_style

    # Class variables
    # Lexer index counter for Nim styling
    _index = 0
    index = 0
    # Styles
    styles = {
        "Default": 0,
        "Comment": 1,
        "Number": 2,
        "DoubleQuotedString": 3,
        "SingleQuotedString": 4,
        "Keyword": 5,
        "TripleSingleQuotedString": 6,
        "TripleDoubleQuotedString": 7,
        "ClassName": 8,
        "FunctionMethodName": 9,
        "Operator": 10,
        "Identifier": 11,
        "CommentBlock": 12,
        "UnclosedString": 13,
        "HighlightedIdentifier": 14,
        "Decorator": 15,
        "CustomKeyword": 16,
    }
    default_color = data.QColor(data.theme.Font.Python.Default[1])
    default_paper = data.QColor(data.theme.Paper.Python.Default)
    default_font = data.QFont(data.current_font_name, data.current_font_size)
    # Styling lists and characters
    keyword_list = list(set(keyword.kwlist + dir(builtins)))
    additional_list = []
    sq = Sequence('\'', ['\'', '\n'], [], styles["SingleQuotedString"], True)
    dq = Sequence('"', ['"', '\n'], [], styles["DoubleQuotedString"], True)
    edq = Sequence('""', [], [], styles["DoubleQuotedString"], True)
    esq = Sequence('\'\'', [], [], styles["DoubleQuotedString"], True)
    tqd = Sequence('\'\'\'', ['\'\'\''], [],
                   styles["TripleSingleQuotedString"], True)
    tqs = Sequence('"""', ['"""'], [], styles["TripleDoubleQuotedString"],
                   True)
    cls = Sequence('class', [':'], ['(', '\n'], styles["ClassName"], False)
    defi = Sequence('def', [], ['('], styles["FunctionMethodName"], False)
    comment = Sequence('#', [], ['\n'], styles["Comment"], True)
    dcomment = Sequence('##', [], ['\n'], styles["CommentBlock"], True)
    decorator = Sequence('@', ['\n'], [' '], styles["Decorator"], True)
    sequence_lists = [
        sq, dq, edq, esq, tqd, tqs, cls, defi, comment, dcomment, decorator
    ]
    multiline_sequence_list = [tqd, tqs]
    sequence_start_chrs = [x.start for x in sequence_lists]
    # Regular expression split sequence to tokenize text
    splitter = re.compile(r"(\\'|\\\"|\(\*|\*\)|\n|\"+|\'+|\#+|\s+|\w+|\W)")
    #Characters that autoindent one level on pressing Return/Enter
    autoindent_characters = [":"]

    def __init__(self, parent=None, additional_keywords=[]):
        """Overridden initialization"""
        # Initialize superclass
        super().__init__()
        # Set the lexer's index
        self.index = CustomPython._index
        CustomPython._index += 1
        # Set the additional keywords
        self.additional_list = ["self"]
        self.additional_list.extend(additional_keywords)
        if lexers.nim_lexers_found == True:
            lexers.nim_lexers.python_set_keywords(self.index,
                                                  additional_keywords)
        # Set the default style values
        self.setDefaultColor(self.default_color)
        self.setDefaultPaper(self.default_paper)
        self.setDefaultFont(self.default_font)
        # Reset autoindentation style
        self.setAutoIndentStyle(0)
        # Set the theme
        self.set_theme(data.theme)

    def language(self):
        return "Python"

    def description(self, style):
        if style <= 16:
            description = "Custom lexer for the Python programming languages"
        else:
            description = ""
        return description

    def defaultStyle(self):
        return self.styles["Default"]

    def braceStyle(self):
        return self.styles["Default"]

    def defaultFont(self, style):
        return data.QFont(data.current_font_name, data.current_font_size)

    def set_theme(self, theme):
        for style in self.styles:
            # Papers
            paper = data.QColor(getattr(theme.Paper.Python, style))
            self.setPaper(paper, self.styles[style])
            # Fonts
            lexers.set_font(self, style, getattr(theme.Font.Python, style))

    if lexers.nim_lexers_found == True:

        def __del__(self):
            lexers.nim_lexers.python_delete_keywords(self.index)

        def styleText(self, start, end):
            editor = self.editor()
            if editor is None:
                return
#            lexers.nim_lexers.python_style_text(
#                self.index, start, end, self, editor
#            )
            lexers.nim_lexers.python_style_test(self.index, start, end)
    else:

        def styleText(self, start, end):
            editor = self.editor()
            if editor is None:
                return
            # Initialize the styling
            self.startStyling(start)
            # Scintilla works with bytes, so we have to adjust the start and end boundaries
            text = bytearray(editor.text(), "utf-8")[start:end].decode("utf-8")
            # Loop optimizations
            setStyling = self.setStyling
            # Initialize comment state and split the text into tokens
            sequence = None
            tokens = [(token, len(bytearray(token, "utf-8")))
                      for token in self.splitter.findall(text)]
            # Check if there is a style(comment, string, ...) stretching on from the previous line
            if start != 0:
                previous_style = editor.SendScintilla(editor.SCI_GETSTYLEAT,
                                                      start - 1)
                for i in self.multiline_sequence_list:
                    if previous_style == i.style:
                        sequence = i
                        break

            # Style the tokens accordingly
            for i, token in enumerate(tokens):
                #                print(token[0].encode("utf-8"))
                token_name = token[0]
                token_length = token[1]
                if sequence != None:
                    if token_name in sequence.stop_sequences:
                        if sequence.add_to_style == True:
                            setStyling(token_length, sequence.style)
                        else:
                            setStyling(token_length, self.styles["Default"])
                        sequence = None
                    elif any(ch in token_name
                             for ch in sequence.stop_characters):
                        if sequence.add_to_style == True:
                            setStyling(token_length, sequence.style)
                        else:
                            setStyling(token_length, self.styles["Default"])
                        sequence = None
                    else:
                        setStyling(token_length, sequence.style)
                elif token_name in self.sequence_start_chrs:
                    for i in self.sequence_lists:
                        if token_name == i.start:
                            if i.stop_sequences == [] and i.stop_characters == []:
                                # Skip styling if both stop sequences and stop characters are empty
                                setStyling(token_length, i.style)
                            else:
                                # Style the sequence and store the reference to it
                                sequence = i
                                if i.add_to_style == True:
                                    setStyling(token_length, sequence.style)
                                else:
                                    if token_name in self.keyword_list:
                                        setStyling(token_length,
                                                   self.styles["Keyword"])
                                    elif token_name in self.additional_list:
                                        setStyling(
                                            token_length,
                                            self.styles["CustomKeyword"])
                                    else:
                                        setStyling(token_length,
                                                   self.styles["Default"])
                            break
                elif token_name in self.keyword_list:
                    setStyling(token_length, self.styles["Keyword"])
                elif token_name in self.additional_list:
                    setStyling(token_length, self.styles["CustomKeyword"])
                elif token_name[0].isdigit():
                    setStyling(token_length, self.styles["Number"])
                else:
                    setStyling(token_length, self.styles["Default"])
示例#25
0
文件: oberon.py 项目: testerclub/ExCo
class Oberon(data.QsciLexerCustom):
    """
    Custom lexer for the Oberon/Oberon-2/Modula/Modula-2 programming languages
    """
    styles = {
        "Default": 0,
        "Comment": 1,
        "Keyword": 2,
        "String": 3,
        "Procedure": 4,
        "Module": 5,
        "Number": 6,
        "Type": 7
    }

    #Class variables
    default_color = data.QColor(data.theme.Font.Oberon.Default[1])
    default_paper = data.QColor(data.theme.Paper.Oberon.Default)
    default_font = data.QFont('Courier', 10)
    keyword_list = [
        'ARRAY', 'IMPORT', 'RETURN', 'BEGIN', 'IN', 'THEN', 'BY', 'IS', 'TO',
        'CASE', 'LOOP', 'Type', 'CONST', 'MOD', 'UNTIL', 'DIV', 'MODULE',
        'VAR', 'DO', 'NIL', 'WHILE', 'ELSE', 'OF', 'WITH', 'ELSIF', 'OR',
        'END', 'POINTER', 'EXIT', 'PROCEDURE', 'FOR', 'RECORD', 'IF', 'REPEAT'
    ]
    types_list = [
        'BOOLEAN', 'CHAR', 'SHORTINT', 'INTEGER', 'LONGINT', 'REAL',
        'LONGREAL', 'SET'
    ]
    splitter = re.compile(r"(\(\*|\*\)|\s+|\w+|\W)")

    def __init__(self, parent=None):
        """Overridden initialization"""
        #Initialize superclass
        super().__init__()
        #Set the default style values
        self.setDefaultColor(self.default_color)
        self.setDefaultPaper(self.default_paper)
        self.setDefaultFont(self.default_font)
        #Reset autoindentation style
        self.setAutoIndentStyle(0)
        #Set the theme
        self.set_theme(data.theme)

    def language(self):
        return "Oberon/Modula-2/Component Pascal"

    def description(self, style):
        if style <= 7:
            description = "Custom lexer for the Oberon/Oberon-2/Modula/Modula-2/Component Pascal programming languages"
        else:
            description = ""
        return description

    def set_theme(self, theme):
        for style in self.styles:
            # Papers
            self.setPaper(data.QColor(theme.Paper.Oberon.Default),
                          self.styles[style])
            # Fonts
            lexers.set_font(self, style, getattr(theme.Font.Oberon, style))

    def styleText(self, start, end):
        """
        Overloaded method for styling text.
        NOTE:
            Very slow if done in Python!
            Using the Cython version is better.
            The fastest would probably be adding the lexer directly into
            the QScintilla source. Maybe never :-)
        """
        #Get the global cython flag
        if lexers.cython_lexers_found == True:
            #Cython module found
            lexers.cython_lexers.style_oberon(start, end, self, self.editor())
        else:
            #Style in pure Python, VERY SLOW!
            editor = self.editor()
            if editor is None:
                return
            #Initialize the styling
            self.startStyling(start)
            #Scintilla works with bytes, so we have to adjust the start and end boundaries
            text = bytearray(editor.text(), "utf-8")[start:end].decode("utf-8")
            #Loop optimizations
            setStyling = self.setStyling
            kw_list = self.keyword_list
            types_list = self.types_list
            DEF = self.styles["Default"]
            KWD = self.styles["Keyword"]
            COM = self.styles["Comment"]
            STR = self.styles["String"]
            PRO = self.styles["Procedure"]
            MOD = self.styles["Module"]
            NUM = self.styles["Number"]
            TYP = self.styles["Type"]
            #Initialize comment state and split the text into tokens
            commenting = False
            stringing = False
            tokens = [(token, len(bytearray(token, "utf-8")))
                      for token in self.splitter.findall(text)]
            #Check if there is a style(comment, string, ...) stretching on from the previous line
            if start != 0:
                previous_style = editor.SendScintilla(editor.SCI_GETSTYLEAT,
                                                      start - 1)
                if previous_style == COM:
                    commenting = True
            #Style the tokens accordingly
            for i, token in enumerate(tokens):
                if commenting == True:
                    #Continuation of comment
                    setStyling(token[1], COM)
                    #Check if comment ends
                    if token[0] == "*)":
                        commenting = False
                elif stringing == True:
                    #Continuation of a string
                    setStyling(token[1], STR)
                    #Check if string ends
                    if token[0] == "\"" or "\n" in token[0]:
                        stringing = False
                elif token[0] == "\"":
                    #Start of a string
                    setStyling(token[1], STR)
                    stringing = True
                elif token[0] in kw_list:
                    #Keyword
                    setStyling(token[1], KWD)
                elif token[0] in types_list:
                    #Keyword
                    setStyling(token[1], TYP)
                elif token[0] == "(*":
                    #Start of a comment
                    setStyling(token[1], COM)
                    commenting = True
                elif i > 1 and tokens[i - 2][0] == "PROCEDURE":
                    #Procedure name
                    setStyling(token[1], PRO)
                elif i > 1 and tokens[i - 2][0] == "MODULE":
                    #Module name (beginning)
                    setStyling(token[1], MOD)
                elif (i > 1 and tokens[i - 2][0]
                      == "END") and (len(tokens) - 1 >= i + 1):
                    #Module or procedure name (name)
                    if ";" in tokens[i + 1][0]:
                        #Procedure end
                        setStyling(token[1], PRO)
                    elif "." in tokens[i + 1][0]:
                        #Module end
                        setStyling(token[1], MOD)
                    else:
                        setStyling(token[1], DEF)
                elif functions.is_number(token[0]):
                    #Number
                    setStyling(token[1], NUM)
                else:
                    setStyling(token[1], DEF)
示例#26
0
文件: settings.py 项目: Mr-ZBin/ExCo
class Editor:
    """
    These are the built-in defaults, attributes should be changed
    in other modules!
    """
    # Default EOL style in editors (EolWindows-CRLF, EolUnix-LF, EolMac-CR)
    end_of_line_mode = data.QsciScintilla.EolUnix
    # Font colors and styles
    font = data.QFont(
        data.current_editor_font_name,
        data.current_editor_font_size
    )
    brace_color = data.QColor(255, 153, 0)
    comment_font = data.current_editor_font_name.encode("utf-8")
    # Edge marker
    edge_marker_color = data.QColor(180, 180, 180, alpha=255)
    edge_marker_column = 90
    # Various
    cursor_line_visible = False
    # Maximum limit of highlighting instances
    maximum_highlights = 300
    # Global width of tabs
    tab_width = 4
    # Zoom factor when a new editor is created (default is 0)
    zoom_factor = 0
    """
    -------------------------------------------
    Keyboard shortcuts
    -------------------------------------------
    """
    class Keys:
        # Custom editor commands
        copy = 'Ctrl+C'
        cut = 'Ctrl+X'
        paste = 'Ctrl+V'
        undo = 'Ctrl+Z'
        redo = 'Ctrl+Y'
        select_all = 'Ctrl+A'
        indent = 'Tab'
        unindent = 'Shift+Tab'
        delete_start_of_word = 'Ctrl+BackSpace'
        delete_end_of_word = 'Ctrl+Delete'
        delete_start_of_line = 'Ctrl+Shift+BackSpace'
        delete_end_of_line = 'Ctrl+Shift+Delete'
        go_to_start = 'Ctrl+Home'
        go_to_end = 'Ctrl+End'
        select_page_up = 'Shift+PageUp'
        select_page_down = 'Shift+PageDown'
        select_to_start = 'Ctrl+Shift+Home'
        select_to_end = 'Ctrl+Shift+End'
        scroll_up = 'PageUp'
        scroll_down = 'PageDown'
        line_cut = 'Ctrl+L'
        line_copy = 'Ctrl+Shift+T'
        line_delete = 'Ctrl+Shift+L'
        line_transpose = 'Ctrl+T'
        line_selection_duplicate = 'Ctrl+D'
        
        @staticmethod
        def check_function(function_name):
            check_list = [x for x in dir(Editor.Keys) if not x.startswith('__')]
            return function_name in check_list
        
        @staticmethod
        def check_combination(combination):
            if combination.startswith("#"):
               combination = combination[1:] 
            check_list = [
                (x, getattr(Editor.Keys, x)) 
                    for x in dir(Editor.Keys) 
                        if not x.startswith('__')
            ]
            for name, keys in check_list:
                if not(isinstance(keys, str)) and not(isinstance(keys, list)):
                    continue
                if isinstance(combination, list):
                    if isinstance(keys, list):
                        for k in keys:
                            for c in combination:
                                if k.strip().lower() == c.strip().lower():
                                    return True
                    else:
                        for c in combination:
                            if keys.strip().lower() == c.strip().lower():
                                return True
                elif isinstance(keys, str):
                    if keys.strip().lower() == combination.strip().lower():
                        return True
            return False
示例#27
0
文件: text.py 项目: Mr-ZBin/ExCo
 def set_theme(self, theme):
     # Papers
     self.setPaper(data.QColor(theme.Paper.Python.Default),
                   self.styles["Default"])
     # Fonts
     lexers.set_font(self, "Default", theme.Font.Python.Default)