/highlighter.py

https://github.com/netconstructor/db_manager · Python · 182 lines · 109 code · 32 blank · 41 comment · 21 complexity · 205737c7246039261ce7d55c385d7264 MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. """
  3. /***************************************************************************
  4. Name : DB Manager
  5. Description : Database manager plugin for QuantumGIS
  6. Date : May 23, 2011
  7. copyright : (C) 2011 by Giuseppe Sucameli
  8. email : brush.tyler@gmail.com
  9. The content of this file is based on
  10. Python Syntax Highlighting Example
  11. Copyright (C) 2009 Carson J. Q. Farmer
  12. ***************************************************************************/
  13. /***************************************************************************
  14. * *
  15. * This program is free software; you can redistribute it and/or modify *
  16. * it under the terms of the GNU General Public License as published by *
  17. * the Free Software Foundation; either version 2 of the License, or *
  18. * (at your option) any later version. *
  19. * *
  20. ***************************************************************************/
  21. """
  22. from PyQt4.QtGui import *
  23. from PyQt4.QtCore import *
  24. class SqlHighlighter(QSyntaxHighlighter):
  25. COLOR_KEYWORD = QColor(0x00,0x00,0xE6)
  26. COLOR_FUNCTION = QColor(0xCE,0x7B,0x00)
  27. COLOR_COMMENT = QColor(0x96,0x96,0x96)
  28. COLOR_CONSTANT = Qt.magenta
  29. COLOR_IDENTIFIER = QColor(0x00,0x99,0x00)
  30. COLOR_PARAMETER = QColor(0x25,0x9D,0x9D)
  31. def __init__(self, editor):
  32. QSyntaxHighlighter.__init__(self, editor)
  33. self.editor = editor
  34. self.rules = []
  35. self.styles = {}
  36. # keyword
  37. format = QTextCharFormat()
  38. format.setForeground( QBrush(self.COLOR_KEYWORD, Qt.SolidPattern) )
  39. #format.setFontWeight( QFont.Bold )
  40. self.styles['keyword'] = format
  41. # function and delimiter
  42. format = QTextCharFormat()
  43. format.setForeground( QBrush(self.COLOR_FUNCTION, Qt.SolidPattern) )
  44. self.styles['function'] = format
  45. self.styles['delimiter'] = format
  46. # identifier
  47. format = QTextCharFormat()
  48. format.setForeground( QBrush(self.COLOR_IDENTIFIER, Qt.SolidPattern) )
  49. self.styles['identifier'] = format
  50. # comment
  51. format = QTextCharFormat()
  52. format.setForeground( QBrush(self.COLOR_COMMENT, Qt.SolidPattern) )
  53. self.styles['comment'] = format
  54. # constant (numbers, strings)
  55. format = QTextCharFormat()
  56. format.setForeground( QBrush(self.COLOR_CONSTANT, Qt.SolidPattern) )
  57. self.styles['constant'] = format
  58. def highlightBlock(self, text):
  59. text = text.toLower()
  60. index = 0
  61. rule_sel = None
  62. rule_index = -1
  63. while index < text.length():
  64. # search for the rule that matches starting from the less index
  65. rule_sel = None
  66. rule_index = -1
  67. rule_length = 0
  68. for rule in self.rules:
  69. regex = rule.regex()
  70. pos = regex.indexIn(text, index)
  71. if pos >= 0:
  72. if rule_sel == None or rule_index > pos:
  73. rule_sel = rule
  74. rule_index = pos
  75. rule_length = regex.cap(0).length()
  76. if rule_sel == None: # no rule matches
  77. break
  78. # apply the rule found before
  79. self.setFormat(rule_index, rule_length, self.styles[rule_sel.type()])
  80. index = rule_index + rule_length
  81. self.setCurrentBlockState( 0 )
  82. # handle with multiline comments
  83. index = 0
  84. if self.previousBlockState() != 1:
  85. index = self.multiLineCommentStart.indexIn(text, index)
  86. while index >= 0:
  87. # if the last applied rule is a single-line comment,
  88. # then avoid multiline comments that start after it
  89. if rule_sel != None and rule_sel.type() == 'comment' and index >= rule_index:
  90. break
  91. pos = self.multiLineCommentEnd.indexIn(text, index)
  92. comment_length = 0
  93. if pos < 0:
  94. self.setCurrentBlockState(1)
  95. comment_length = text.length() - index;
  96. else:
  97. comment_length = pos - index + self.multiLineCommentEnd.cap(0).length()
  98. self.setFormat(index, comment_length, self.styles['comment'])
  99. index = self.multiLineCommentStart.indexIn(text, index + comment_length)
  100. def load(self, db=None):
  101. self.rules = []
  102. if False and db:
  103. rules = db.connector.getSqlDictionary()
  104. else:
  105. from .sql_dictionary import getSqlDictionary
  106. rules = getSqlDictionary( db.connection().typeName() if db else None )
  107. for name in self.styles.keys():
  108. if not rules.has_key(name):
  109. continue
  110. for value in rules[name]:
  111. regex = QRegExp( u"\\b%s\\b" % QRegExp.escape(value) )
  112. rule = HighlightingRule(name, regex)
  113. self.rules.append( rule )
  114. # delimiter
  115. regex = QRegExp( "[\)\(]" )
  116. rule = HighlightingRule('delimiter', regex)
  117. self.rules.append( rule )
  118. # identifier
  119. regex = QRegExp( r'"[^"\\]*(\\.[^"\\]*)*"' )
  120. regex.setMinimal( True )
  121. rule = HighlightingRule('identifier', regex)
  122. self.rules.append( rule )
  123. # constant (numbers, strings)
  124. # string
  125. regex = QRegExp( r"'[^'\\]*(\\.[^'\\]*)*'" )
  126. regex.setMinimal( True )
  127. rule = HighlightingRule('constant', regex)
  128. self.rules.append( rule )
  129. # number
  130. regex = QRegExp( r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b' )
  131. regex.setMinimal( True )
  132. rule = HighlightingRule('constant', regex)
  133. self.rules.append( rule )
  134. # single-line comment
  135. regex = QRegExp( "--.*$" )
  136. rule = HighlightingRule('comment', regex)
  137. self.rules.append( rule )
  138. # multi-line comment
  139. self.multiLineCommentStart = QRegExp( "/\\*" )
  140. self.multiLineCommentEnd = QRegExp( "\\*/" )
  141. class HighlightingRule:
  142. def __init__(self, typ, regex):
  143. self._type = typ
  144. self._regex = regex
  145. def type(self):
  146. return self._type
  147. def regex(self):
  148. return QRegExp(self._regex)