Add conversion of WeeChat colors to Qt colors, add section "color" in config file
This commit is contained in:
		
							parent
							
								
									c728febdd5
								
							
						
					
					
						commit
						3a5ec0c163
					
				
					 6 changed files with 277 additions and 30 deletions
				
			
		| 
						 | 
					@ -98,7 +98,7 @@ class BufferWidget(QtGui.QWidget):
 | 
				
			||||||
        # splitter with chat + nicklist
 | 
					        # splitter with chat + nicklist
 | 
				
			||||||
        self.chat_nicklist = QtGui.QSplitter()
 | 
					        self.chat_nicklist = QtGui.QSplitter()
 | 
				
			||||||
        self.chat_nicklist.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
 | 
					        self.chat_nicklist.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
 | 
				
			||||||
        self.chat = ChatTextEdit()
 | 
					        self.chat = ChatTextEdit(debug=False)
 | 
				
			||||||
        self.chat_nicklist.addWidget(self.chat)
 | 
					        self.chat_nicklist.addWidget(self.chat)
 | 
				
			||||||
        self.nicklist = GenericListWidget()
 | 
					        self.nicklist = GenericListWidget()
 | 
				
			||||||
        if not display_nicklist:
 | 
					        if not display_nicklist:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,37 +27,98 @@ import datetime
 | 
				
			||||||
import qt_compat
 | 
					import qt_compat
 | 
				
			||||||
QtCore = qt_compat.import_module('QtCore')
 | 
					QtCore = qt_compat.import_module('QtCore')
 | 
				
			||||||
QtGui = qt_compat.import_module('QtGui')
 | 
					QtGui = qt_compat.import_module('QtGui')
 | 
				
			||||||
 | 
					import config
 | 
				
			||||||
 | 
					import weechat.color as color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChatTextEdit(QtGui.QTextEdit):
 | 
					class ChatTextEdit(QtGui.QTextEdit):
 | 
				
			||||||
    """Chat area."""
 | 
					    """Chat area."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args):
 | 
					    def __init__(self, debug, *args):
 | 
				
			||||||
        apply(QtGui.QTextEdit.__init__, (self,) + args)
 | 
					        apply(QtGui.QTextEdit.__init__, (self,) + args)
 | 
				
			||||||
 | 
					        self.debug = debug
 | 
				
			||||||
        self.readOnly = True
 | 
					        self.readOnly = True
 | 
				
			||||||
        self.setFocusPolicy(QtCore.Qt.NoFocus)
 | 
					        self.setFocusPolicy(QtCore.Qt.NoFocus)
 | 
				
			||||||
        self.setFontFamily('monospace')
 | 
					        self.setFontFamily('monospace')
 | 
				
			||||||
 | 
					        self._textcolor = self.textColor()
 | 
				
			||||||
 | 
					        self._bgcolor = QtGui.QColor('#FFFFFF')
 | 
				
			||||||
 | 
					        self._setcolorcode = { 'F': (self.setTextColor, self._textcolor),
 | 
				
			||||||
 | 
					                               'B': (self.setTextBackgroundColor, self._bgcolor) }
 | 
				
			||||||
 | 
					        self._setfont = { '*': self.setFontWeight,
 | 
				
			||||||
 | 
					                          '_': self.setFontUnderline,
 | 
				
			||||||
 | 
					                          '/': self.setFontItalic }
 | 
				
			||||||
 | 
					        self._fontvalues = { False: { '*': QtGui.QFont.Normal, '_': False, '/': False },
 | 
				
			||||||
 | 
					                             True: { '*': QtGui.QFont.Bold, '_': True, '/': True } }
 | 
				
			||||||
 | 
					        self._color = color.Color(config.color_options(), self.debug)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def display(self, time, prefix, text, color=None):
 | 
					    def display(self, time, prefix, text, forcecolor=None):
 | 
				
			||||||
        oldcolor = self.textColor()
 | 
					 | 
				
			||||||
        if time == 0:
 | 
					        if time == 0:
 | 
				
			||||||
            d = datetime.datetime.now()
 | 
					            d = datetime.datetime.now()
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            d = datetime.datetime.fromtimestamp(float(time))
 | 
					            d = datetime.datetime.fromtimestamp(float(time))
 | 
				
			||||||
        self.setTextColor(QtGui.QColor('#999999'))
 | 
					        self.setTextColor(QtGui.QColor('#999999'))
 | 
				
			||||||
        self.insertPlainText(d.strftime('%H:%M '))
 | 
					        self.insertPlainText(d.strftime('%H:%M '))
 | 
				
			||||||
        self.setTextColor(oldcolor)
 | 
					        prefix = self._color.convert(prefix)
 | 
				
			||||||
 | 
					        text = self._color.convert(text)
 | 
				
			||||||
 | 
					        if forcecolor:
 | 
				
			||||||
 | 
					            if prefix:
 | 
				
			||||||
 | 
					                prefix = '\x01(F%s)%s' % (forcecolor, prefix)
 | 
				
			||||||
 | 
					            text = '\x01(F%s)%s' % (forcecolor, text)
 | 
				
			||||||
        if prefix:
 | 
					        if prefix:
 | 
				
			||||||
            self.insertPlainText(str(prefix).decode('utf-8') + ' ')
 | 
					            self._display_with_colors(str(prefix).decode('utf-8') + ' ')
 | 
				
			||||||
        if color:
 | 
					        if text:
 | 
				
			||||||
            self.setTextColor(QtGui.QColor(color))
 | 
					            self._display_with_colors(str(text).decode('utf-8'))
 | 
				
			||||||
        self.insertPlainText(str(text).decode('utf-8'))
 | 
					            if text[-1:] != '\n':
 | 
				
			||||||
        if text[-1:] != '\n':
 | 
					                self.insertPlainText('\n')
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
            self.insertPlainText('\n')
 | 
					            self.insertPlainText('\n')
 | 
				
			||||||
        if color:
 | 
					 | 
				
			||||||
            self.setTextColor(oldcolor)
 | 
					 | 
				
			||||||
        self.scroll_bottom()
 | 
					        self.scroll_bottom()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _display_with_colors(self, string):
 | 
				
			||||||
 | 
					        self.setTextColor(self._textcolor)
 | 
				
			||||||
 | 
					        self.setTextBackgroundColor(self._bgcolor)
 | 
				
			||||||
 | 
					        self._reset_attributes()
 | 
				
			||||||
 | 
					        items = string.split('\x01')
 | 
				
			||||||
 | 
					        for i, item in enumerate(items):
 | 
				
			||||||
 | 
					            if i > 0 and item.startswith('('):
 | 
				
			||||||
 | 
					                pos = item.find(')')
 | 
				
			||||||
 | 
					                if pos >= 2:
 | 
				
			||||||
 | 
					                    action = item[1]
 | 
				
			||||||
 | 
					                    code = item[2:pos]
 | 
				
			||||||
 | 
					                    if action == '+':
 | 
				
			||||||
 | 
					                        # set attribute
 | 
				
			||||||
 | 
					                        self._set_attribute(code[0], True)
 | 
				
			||||||
 | 
					                    elif action == '-':
 | 
				
			||||||
 | 
					                        # remove attribute
 | 
				
			||||||
 | 
					                        self._set_attribute(code[0], False)
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        # reset attributes and color
 | 
				
			||||||
 | 
					                        if code == 'r':
 | 
				
			||||||
 | 
					                            self._reset_attributes()
 | 
				
			||||||
 | 
					                            self._setcolorcode[action][0](self._setcolorcode[action][1])
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            # set attributes + color
 | 
				
			||||||
 | 
					                            while code.startswith(('*', '!', '/', '_', '|', 'r')):
 | 
				
			||||||
 | 
					                                if code[0] == 'r':
 | 
				
			||||||
 | 
					                                    self._reset_attributes()
 | 
				
			||||||
 | 
					                                elif code[0] in self._setfont:
 | 
				
			||||||
 | 
					                                    self._set_attribute(code[0], not self._font[code[0]])
 | 
				
			||||||
 | 
					                                code = code[1:]
 | 
				
			||||||
 | 
					                            if code:
 | 
				
			||||||
 | 
					                                self._setcolorcode[action][0](QtGui.QColor(code))
 | 
				
			||||||
 | 
					                    item = item[pos+1:]
 | 
				
			||||||
 | 
					            if len(item) > 0:
 | 
				
			||||||
 | 
					                self.insertPlainText(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _reset_attributes(self):
 | 
				
			||||||
 | 
					        self._font = {}
 | 
				
			||||||
 | 
					        for attr in self._setfont:
 | 
				
			||||||
 | 
					            self._set_attribute(attr, False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _set_attribute(self, attr, value):
 | 
				
			||||||
 | 
					        self._font[attr] = value
 | 
				
			||||||
 | 
					        self._setfont[attr](self._fontvalues[self._font[attr]][attr])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def scroll_bottom(self):
 | 
					    def scroll_bottom(self):
 | 
				
			||||||
        bar = self.verticalScrollBar()
 | 
					        bar = self.verticalScrollBar()
 | 
				
			||||||
        bar.setValue(bar.maximum())
 | 
					        bar.setValue(bar.maximum())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,11 +24,12 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os, ConfigParser
 | 
					import os, ConfigParser
 | 
				
			||||||
 | 
					import weechat.color as color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DIR = '%s/.qweechat' % os.getenv('HOME')
 | 
					CONFIG_DIR = '%s/.qweechat' % os.getenv('HOME')
 | 
				
			||||||
CONFIG_FILENAME = '%s/qweechat.conf' % CONFIG_DIR
 | 
					CONFIG_FILENAME = '%s/qweechat.conf' % CONFIG_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFAULT_SECTIONS = ('relay', 'look')
 | 
					CONFIG_DEFAULT_SECTIONS = ('relay', 'look', 'color')
 | 
				
			||||||
CONFIG_DEFAULT_OPTIONS = (('relay.server', ''),
 | 
					CONFIG_DEFAULT_OPTIONS = (('relay.server', ''),
 | 
				
			||||||
                          ('relay.port', ''),
 | 
					                          ('relay.port', ''),
 | 
				
			||||||
                          ('relay.password', ''),
 | 
					                          ('relay.password', ''),
 | 
				
			||||||
| 
						 | 
					@ -36,9 +37,51 @@ CONFIG_DEFAULT_OPTIONS = (('relay.server', ''),
 | 
				
			||||||
                          ('look.debug', 'off'),
 | 
					                          ('look.debug', 'off'),
 | 
				
			||||||
                          ('look.statusbar', 'off'))
 | 
					                          ('look.statusbar', 'off'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Default colors for WeeChat color options (option name, #rgb value)
 | 
				
			||||||
 | 
					CONFIG_DEFAULT_COLOR_OPTIONS = (('separator', '#000066'), # 0
 | 
				
			||||||
 | 
					                                ('chat', '#000000'), # 1
 | 
				
			||||||
 | 
					                                ('chat_time', '#999999'), # 2
 | 
				
			||||||
 | 
					                                ('chat_time_delimiters', '#000000'), # 3
 | 
				
			||||||
 | 
					                                ('chat_prefix_error', '#FF6633'), # 4
 | 
				
			||||||
 | 
					                                ('chat_prefix_network', '#990099'), # 5
 | 
				
			||||||
 | 
					                                ('chat_prefix_action', '#000000'), # 6
 | 
				
			||||||
 | 
					                                ('chat_prefix_join', '#00CC00'), # 7
 | 
				
			||||||
 | 
					                                ('chat_prefix_quit', '#CC0000'), # 8
 | 
				
			||||||
 | 
					                                ('chat_prefix_more', '#CC00FF'), # 9
 | 
				
			||||||
 | 
					                                ('chat_prefix_suffix', '#330099'), # 10
 | 
				
			||||||
 | 
					                                ('chat_buffer', '#000000'), # 11
 | 
				
			||||||
 | 
					                                ('chat_server', '#000000'), # 12
 | 
				
			||||||
 | 
					                                ('chat_channel', '#000000'), # 13
 | 
				
			||||||
 | 
					                                ('chat_nick', '#000000'), # 14
 | 
				
			||||||
 | 
					                                ('chat_nick_self', '*#000000'), # 15
 | 
				
			||||||
 | 
					                                ('chat_nick_other', '#000000'), # 16
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 17 (nick1 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 18 (nick2 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 19 (nick3 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 20 (nick4 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 21 (nick5 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 22 (nick6 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 23 (nick7 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 24 (nick8 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 25 (nick9 -- obsolete)
 | 
				
			||||||
 | 
					                                ('', '#000000'), # 26 (nick10 -- obsolete)
 | 
				
			||||||
 | 
					                                ('chat_host', '#666666'), # 27
 | 
				
			||||||
 | 
					                                ('chat_delimiters', '#9999FF'), # 28
 | 
				
			||||||
 | 
					                                ('chat_highlight', '#3399CC'), # 29
 | 
				
			||||||
 | 
					                                ('chat_read_marker', '#000000'), # 30
 | 
				
			||||||
 | 
					                                ('chat_text_found', '#000000'), # 31
 | 
				
			||||||
 | 
					                                ('chat_value', '#000000'), # 32
 | 
				
			||||||
 | 
					                                ('chat_prefix_buffer', '#000000'), # 33
 | 
				
			||||||
 | 
					                                ('chat_tags', '#000000'), # 34
 | 
				
			||||||
 | 
					                                ('chat_inactive_window', '#000000'), # 35
 | 
				
			||||||
 | 
					                                ('chat_inactive_buffer', '#000000'), # 36
 | 
				
			||||||
 | 
					                                ('chat_prefix_buffer_inactive_buffer', '#000000')) # 37
 | 
				
			||||||
 | 
					config_color_options = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def read():
 | 
					def read():
 | 
				
			||||||
    """Read config file."""
 | 
					    """Read config file."""
 | 
				
			||||||
 | 
					    global config_color_options
 | 
				
			||||||
    config = ConfigParser.RawConfigParser()
 | 
					    config = ConfigParser.RawConfigParser()
 | 
				
			||||||
    if os.path.isfile(CONFIG_FILENAME):
 | 
					    if os.path.isfile(CONFIG_FILENAME):
 | 
				
			||||||
        config.read(CONFIG_FILENAME)
 | 
					        config.read(CONFIG_FILENAME)
 | 
				
			||||||
| 
						 | 
					@ -51,6 +94,19 @@ def read():
 | 
				
			||||||
        section, name = option[0].split('.', 1)
 | 
					        section, name = option[0].split('.', 1)
 | 
				
			||||||
        if not config.has_option(section, name):
 | 
					        if not config.has_option(section, name):
 | 
				
			||||||
            config.set(section, name, option[1])
 | 
					            config.set(section, name, option[1])
 | 
				
			||||||
 | 
					    section = 'color'
 | 
				
			||||||
 | 
					    for option in reversed(CONFIG_DEFAULT_COLOR_OPTIONS):
 | 
				
			||||||
 | 
					        if option[0] and not config.has_option(section, option[0]):
 | 
				
			||||||
 | 
					            config.set(section, option[0], option[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # build list of color options
 | 
				
			||||||
 | 
					    config_color_options = []
 | 
				
			||||||
 | 
					    for option in CONFIG_DEFAULT_COLOR_OPTIONS:
 | 
				
			||||||
 | 
					        if option[0]:
 | 
				
			||||||
 | 
					            config_color_options.append(config.get('color', option[0]))
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            config_color_options.append('#000000')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return config
 | 
					    return config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def write(config):
 | 
					def write(config):
 | 
				
			||||||
| 
						 | 
					@ -59,3 +115,7 @@ def write(config):
 | 
				
			||||||
        os.mkdir(CONFIG_DIR, 0755)
 | 
					        os.mkdir(CONFIG_DIR, 0755)
 | 
				
			||||||
    with open(CONFIG_FILENAME, 'wb') as cfg:
 | 
					    with open(CONFIG_FILENAME, 'wb') as cfg:
 | 
				
			||||||
        config.write(cfg)
 | 
					        config.write(cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def color_options():
 | 
				
			||||||
 | 
					    global config_color_options
 | 
				
			||||||
 | 
					    return config_color_options
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ class DebugDialog(QtGui.QDialog):
 | 
				
			||||||
        self.resize(640, 480)
 | 
					        self.resize(640, 480)
 | 
				
			||||||
        self.setWindowTitle('Debug console')
 | 
					        self.setWindowTitle('Debug console')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.chat = ChatTextEdit()
 | 
					        self.chat = ChatTextEdit(debug=True)
 | 
				
			||||||
        self.input = InputLineEdit(self.chat)
 | 
					        self.input = InputLineEdit(self.chat)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        vbox = QtGui.QVBoxLayout()
 | 
					        vbox = QtGui.QVBoxLayout()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,6 @@ QtCore = qt_compat.import_module('QtCore')
 | 
				
			||||||
QtGui = qt_compat.import_module('QtGui')
 | 
					QtGui = qt_compat.import_module('QtGui')
 | 
				
			||||||
import config
 | 
					import config
 | 
				
			||||||
import weechat.protocol as protocol
 | 
					import weechat.protocol as protocol
 | 
				
			||||||
import weechat.color as color
 | 
					 | 
				
			||||||
from network import Network
 | 
					from network import Network
 | 
				
			||||||
from connection import ConnectionDialog
 | 
					from connection import ConnectionDialog
 | 
				
			||||||
from buffer import BufferListWidget, Buffer
 | 
					from buffer import BufferListWidget, Buffer
 | 
				
			||||||
| 
						 | 
					@ -153,7 +152,7 @@ class MainWindow(QtGui.QMainWindow):
 | 
				
			||||||
        if self.network.is_connected():
 | 
					        if self.network.is_connected():
 | 
				
			||||||
            message = 'input %s %s\n' % (full_name, text)
 | 
					            message = 'input %s %s\n' % (full_name, text)
 | 
				
			||||||
            self.network.send_to_weechat(message)
 | 
					            self.network.send_to_weechat(message)
 | 
				
			||||||
            self.debug_display(0, '<==', message, color='red')
 | 
					            self.debug_display(0, '<==', message, forcecolor='#AA0000')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def open_preferences_dialog(self):
 | 
					    def open_preferences_dialog(self):
 | 
				
			||||||
        pass # TODO
 | 
					        pass # TODO
 | 
				
			||||||
| 
						 | 
					@ -180,8 +179,8 @@ class MainWindow(QtGui.QMainWindow):
 | 
				
			||||||
                text = '(debug_%s)%s' % (text[1:pos], text[pos+1:])
 | 
					                text = '(debug_%s)%s' % (text[1:pos], text[pos+1:])
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                text = '(debug) %s' % text
 | 
					                text = '(debug) %s' % text
 | 
				
			||||||
 | 
					            self.debug_display(0, '<==', text, forcecolor='#AA0000')
 | 
				
			||||||
            self.network.send_to_weechat(text + '\n')
 | 
					            self.network.send_to_weechat(text + '\n')
 | 
				
			||||||
            self.debug_display(0, '<==', text, color='red')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def debug_dialog_closed(self, result):
 | 
					    def debug_dialog_closed(self, result):
 | 
				
			||||||
        self.debug_dialog = None
 | 
					        self.debug_dialog = None
 | 
				
			||||||
| 
						 | 
					@ -210,7 +209,7 @@ class MainWindow(QtGui.QMainWindow):
 | 
				
			||||||
    def network_status_changed(self, status, extra):
 | 
					    def network_status_changed(self, status, extra):
 | 
				
			||||||
        if self.config.getboolean('look', 'statusbar'):
 | 
					        if self.config.getboolean('look', 'statusbar'):
 | 
				
			||||||
            self.statusBar().showMessage(status)
 | 
					            self.statusBar().showMessage(status)
 | 
				
			||||||
        self.debug_display(0, '', status, color='blue')
 | 
					        self.debug_display(0, '', status, forcecolor='#0000AA')
 | 
				
			||||||
        self.network_status_set(status, extra)
 | 
					        self.network_status_set(status, extra)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def network_status_set(self, status, extra):
 | 
					    def network_status_set(self, status, extra):
 | 
				
			||||||
| 
						 | 
					@ -236,7 +235,7 @@ class MainWindow(QtGui.QMainWindow):
 | 
				
			||||||
        self.debug_display(0, '==>',
 | 
					        self.debug_display(0, '==>',
 | 
				
			||||||
                           'message (%d bytes):\n%s'
 | 
					                           'message (%d bytes):\n%s'
 | 
				
			||||||
                           % (len(message), protocol.hex_and_ascii(message, 20)),
 | 
					                           % (len(message), protocol.hex_and_ascii(message, 20)),
 | 
				
			||||||
                           color='green')
 | 
					                           forcecolor='#008800')
 | 
				
			||||||
        proto = protocol.Protocol()
 | 
					        proto = protocol.Protocol()
 | 
				
			||||||
        message = proto.decode(str(message))
 | 
					        message = proto.decode(str(message))
 | 
				
			||||||
        if message.uncompressed:
 | 
					        if message.uncompressed:
 | 
				
			||||||
| 
						 | 
					@ -244,7 +243,7 @@ class MainWindow(QtGui.QMainWindow):
 | 
				
			||||||
                               'message uncompressed (%d bytes):\n%s'
 | 
					                               'message uncompressed (%d bytes):\n%s'
 | 
				
			||||||
                               % (message.size_uncompressed,
 | 
					                               % (message.size_uncompressed,
 | 
				
			||||||
                                  protocol.hex_and_ascii(message.uncompressed, 20)),
 | 
					                                  protocol.hex_and_ascii(message.uncompressed, 20)),
 | 
				
			||||||
                               color='green')
 | 
					                               forcecolor='#008800')
 | 
				
			||||||
        self.debug_display(0, '', 'Message: %s' % message)
 | 
					        self.debug_display(0, '', 'Message: %s' % message)
 | 
				
			||||||
        self.parse_message(message)
 | 
					        self.parse_message(message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,8 +275,8 @@ class MainWindow(QtGui.QMainWindow):
 | 
				
			||||||
                        index = [i for i, b in enumerate(self.buffers) if b.pointer() == ptrbuf]
 | 
					                        index = [i for i, b in enumerate(self.buffers) if b.pointer() == ptrbuf]
 | 
				
			||||||
                        if index:
 | 
					                        if index:
 | 
				
			||||||
                            self.buffers[index[0]].widget.chat.display(item['date'],
 | 
					                            self.buffers[index[0]].widget.chat.display(item['date'],
 | 
				
			||||||
                                                                       color.remove(item['prefix']),
 | 
					                                                                       item['prefix'],
 | 
				
			||||||
                                                                       color.remove(item['message']))
 | 
					                                                                       item['message'])
 | 
				
			||||||
        elif message.msgid in ('_nicklist', 'nicklist'):
 | 
					        elif message.msgid in ('_nicklist', 'nicklist'):
 | 
				
			||||||
            buffer_nicklist = {}
 | 
					            buffer_nicklist = {}
 | 
				
			||||||
            for obj in message.objects:
 | 
					            for obj in message.objects:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,15 +29,142 @@ RE_COLOR_ATTRS = r'[*!/_|]*'
 | 
				
			||||||
RE_COLOR_STD = r'(?:%s\d{2})' % RE_COLOR_ATTRS
 | 
					RE_COLOR_STD = r'(?:%s\d{2})' % RE_COLOR_ATTRS
 | 
				
			||||||
RE_COLOR_EXT = r'(?:@%s\d{5})' % RE_COLOR_ATTRS
 | 
					RE_COLOR_EXT = r'(?:@%s\d{5})' % RE_COLOR_ATTRS
 | 
				
			||||||
RE_COLOR_ANY = r'(?:%s|%s)' % (RE_COLOR_STD, RE_COLOR_EXT)
 | 
					RE_COLOR_ANY = r'(?:%s|%s)' % (RE_COLOR_STD, RE_COLOR_EXT)
 | 
				
			||||||
 | 
					# \x19: color code, \x1A: set attribute, \x1B: remove attribute, \x1C: reset
 | 
				
			||||||
RE_COLOR = re.compile(r'(\x19(?:\d{2}|F%s|B\d{2}|B@\d{5}|\\*%s(,%s)?|@\d{5}|b.|\x1C))|\x1A.|\x1B.|\x1C'
 | 
					RE_COLOR = re.compile(r'(\x19(?:\d{2}|F%s|B\d{2}|B@\d{5}|\\*%s(,%s)?|@\d{5}|b.|\x1C))|\x1A.|\x1B.|\x1C'
 | 
				
			||||||
                      % (RE_COLOR_ANY, RE_COLOR_ANY, RE_COLOR_ANY))
 | 
					                      % (RE_COLOR_ANY, RE_COLOR_ANY, RE_COLOR_ANY))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _replace_color(match):
 | 
					TERMINAL_COLORS = \
 | 
				
			||||||
    return match.group(0)
 | 
					    '000000cd000000cd00cdcd000000cdcd00cd00cdcde5e5e54d4d4dff000000ff00ffff000000ffff00ff00ffffffffff' \
 | 
				
			||||||
 | 
					    '00000000002a0000550000800000aa0000d4002a00002a2a002a55002a80002aaa002ad400550000552a005555005580' \
 | 
				
			||||||
 | 
					    '0055aa0055d400800000802a0080550080800080aa0080d400aa0000aa2a00aa5500aa8000aaaa00aad400d40000d42a' \
 | 
				
			||||||
 | 
					    '00d45500d48000d4aa00d4d42a00002a002a2a00552a00802a00aa2a00d42a2a002a2a2a2a2a552a2a802a2aaa2a2ad4' \
 | 
				
			||||||
 | 
					    '2a55002a552a2a55552a55802a55aa2a55d42a80002a802a2a80552a80802a80aa2a80d42aaa002aaa2a2aaa552aaa80' \
 | 
				
			||||||
 | 
					    '2aaaaa2aaad42ad4002ad42a2ad4552ad4802ad4aa2ad4d455000055002a5500555500805500aa5500d4552a00552a2a' \
 | 
				
			||||||
 | 
					    '552a55552a80552aaa552ad455550055552a5555555555805555aa5555d455800055802a5580555580805580aa5580d4' \
 | 
				
			||||||
 | 
					    '55aa0055aa2a55aa5555aa8055aaaa55aad455d40055d42a55d45555d48055d4aa55d4d480000080002a800055800080' \
 | 
				
			||||||
 | 
					    '8000aa8000d4802a00802a2a802a55802a80802aaa802ad480550080552a8055558055808055aa8055d480800080802a' \
 | 
				
			||||||
 | 
					    '8080558080808080aa8080d480aa0080aa2a80aa5580aa8080aaaa80aad480d40080d42a80d45580d48080d4aa80d4d4' \
 | 
				
			||||||
 | 
					    'aa0000aa002aaa0055aa0080aa00aaaa00d4aa2a00aa2a2aaa2a55aa2a80aa2aaaaa2ad4aa5500aa552aaa5555aa5580' \
 | 
				
			||||||
 | 
					    'aa55aaaa55d4aa8000aa802aaa8055aa8080aa80aaaa80d4aaaa00aaaa2aaaaa55aaaa80aaaaaaaaaad4aad400aad42a' \
 | 
				
			||||||
 | 
					    'aad455aad480aad4aaaad4d4d40000d4002ad40055d40080d400aad400d4d42a00d42a2ad42a55d42a80d42aaad42ad4' \
 | 
				
			||||||
 | 
					    'd45500d4552ad45555d45580d455aad455d4d48000d4802ad48055d48080d480aad480d4d4aa00d4aa2ad4aa55d4aa80' \
 | 
				
			||||||
 | 
					    'd4aaaad4aad4d4d400d4d42ad4d455d4d480d4d4aad4d4d40808081212121c1c1c2626263030303a3a3a4444444e4e4e' \
 | 
				
			||||||
 | 
					    '5858586262626c6c6c7676768080808a8a8a9494949e9e9ea8a8a8b2b2b2bcbcbcc6c6c6d0d0d0dadadae4e4e4eeeeee'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def remove(text):
 | 
					# WeeChat basic colors (color name, index in terminal colors)
 | 
				
			||||||
    """Remove colors in a WeeChat string."""
 | 
					WEECHAT_BASIC_COLORS = (('default', 0), ('black', 0), ('darkgray', 8), ('red', 1),
 | 
				
			||||||
    if not text:
 | 
					                        ('lightred', 9), ('green', 2), ('lightgreen', 10), ('brown', 3),
 | 
				
			||||||
        return text
 | 
					                        ('yellow', 11), ('blue', 4), ('lightblue', 12), ('magenta', 5),
 | 
				
			||||||
    return re.sub(RE_COLOR, '', text)
 | 
					                        ('lightmagenta', 13), ('cyan', 6), ('lightcyan', 14), ('gray', 7),
 | 
				
			||||||
    #return RE_COLOR.sub(_replace_color, text)
 | 
					                        ('white', 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Color():
 | 
				
			||||||
 | 
					    def __init__(self, color_options, debug=False):
 | 
				
			||||||
 | 
					        self.color_options = color_options
 | 
				
			||||||
 | 
					        self.debug = debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _rgb_color(self, index):
 | 
				
			||||||
 | 
					        color = TERMINAL_COLORS[index*6:(index*6)+6]
 | 
				
			||||||
 | 
					        r = int(color[0:2], 16) * 0.85
 | 
				
			||||||
 | 
					        g = int(color[2:4], 16) * 0.85
 | 
				
			||||||
 | 
					        b = int(color[4:6], 16) * 0.85
 | 
				
			||||||
 | 
					        return '%02x%02x%02x' % (r, g, b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _convert_weechat_color(self, color):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            index = int(color)
 | 
				
			||||||
 | 
					            return '\x01(Fr%s)' % self.color_options[index]
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            print 'Error decoding WeeChat color "%s"' % color
 | 
				
			||||||
 | 
					            return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _convert_terminal_color(self, fg_bg, attrs, color):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            index = int(color)
 | 
				
			||||||
 | 
					            return '\x01(%s%s#%s)' % (fg_bg, attrs, self._rgb_color(index))
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            print 'Error decoding terminal color "%s"' % color
 | 
				
			||||||
 | 
					            return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _convert_color_attr(self, fg_bg, color):
 | 
				
			||||||
 | 
					        extended = False
 | 
				
			||||||
 | 
					        if color[0].startswith('@'):
 | 
				
			||||||
 | 
					            extended = True
 | 
				
			||||||
 | 
					            color = color[1:]
 | 
				
			||||||
 | 
					        attrs = ''
 | 
				
			||||||
 | 
					        keep_attrs = False
 | 
				
			||||||
 | 
					        while color.startswith(('*', '!', '/', '_', '|')):
 | 
				
			||||||
 | 
					            if color[0] == '|':
 | 
				
			||||||
 | 
					                keep_attrs = True
 | 
				
			||||||
 | 
					            attrs += color[0]
 | 
				
			||||||
 | 
					            color = color[1:]
 | 
				
			||||||
 | 
					        if extended:
 | 
				
			||||||
 | 
					            return self._convert_terminal_color(fg_bg, attrs, color)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            index = int(color)
 | 
				
			||||||
 | 
					            return self._convert_terminal_color(fg_bg, attrs, WEECHAT_BASIC_COLORS[index][1])
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            print 'Error decoding color "%s"' % color
 | 
				
			||||||
 | 
					            return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _attrcode_to_char(self, code):
 | 
				
			||||||
 | 
					        codes = { '\x01': '*', '\x02': '!', '\x03': '/', '\x04': '_' }
 | 
				
			||||||
 | 
					        return codes.get(code, '')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _convert_color(self, match):
 | 
				
			||||||
 | 
					        color = match.group(0)
 | 
				
			||||||
 | 
					        if color[0] == '\x19':
 | 
				
			||||||
 | 
					            if color[1] == 'b':
 | 
				
			||||||
 | 
					                # bar code, ignored
 | 
				
			||||||
 | 
					                return ''
 | 
				
			||||||
 | 
					            elif color[1] == '\x1C':
 | 
				
			||||||
 | 
					                # reset
 | 
				
			||||||
 | 
					                return '\x01(Fr)\x01(Br)'
 | 
				
			||||||
 | 
					            elif color[1] in ('F', 'B'):
 | 
				
			||||||
 | 
					                # foreground or background
 | 
				
			||||||
 | 
					                return self._convert_color_attr(color[1], color[2:])
 | 
				
			||||||
 | 
					            elif color[1] == '*':
 | 
				
			||||||
 | 
					                # foreground with optional background
 | 
				
			||||||
 | 
					                items = color[2:].split(',')
 | 
				
			||||||
 | 
					                s = self._convert_color_attr('F', items[0])
 | 
				
			||||||
 | 
					                if len(items) > 1:
 | 
				
			||||||
 | 
					                    s += self._convert_color_attr('B', items[1])
 | 
				
			||||||
 | 
					                return s
 | 
				
			||||||
 | 
					            elif color[1] == '@':
 | 
				
			||||||
 | 
					                # direct ncurses pair number, ignored
 | 
				
			||||||
 | 
					                return ''
 | 
				
			||||||
 | 
					            if color[1:].isdigit():
 | 
				
			||||||
 | 
					                return self._convert_weechat_color(int(color[1:]))
 | 
				
			||||||
 | 
					            # color code
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					        elif color[0] == '\x1A':
 | 
				
			||||||
 | 
					            # set attribute
 | 
				
			||||||
 | 
					            return '\x01(+%s)' % self._attrcode_to_char(color[1])
 | 
				
			||||||
 | 
					        elif color[0] == '\x1B':
 | 
				
			||||||
 | 
					            # remove attribute
 | 
				
			||||||
 | 
					            return '\x01(-%s)' % self._attrcode_to_char(color[1])
 | 
				
			||||||
 | 
					        elif color[0] == '\x1C':
 | 
				
			||||||
 | 
					            # reset
 | 
				
			||||||
 | 
					            return '\x01(Fr)\x01(Br)'
 | 
				
			||||||
 | 
					        # should never be executed!
 | 
				
			||||||
 | 
					        return match.group(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _convert_color_debug(self, match):
 | 
				
			||||||
 | 
					        group = match.group(0)
 | 
				
			||||||
 | 
					        for code in (0x01, 0x02, 0x03, 0x04, 0x19, 0x1A, 0x1B):
 | 
				
			||||||
 | 
					            group = group.replace(chr(code), '<x%02X>' % code)
 | 
				
			||||||
 | 
					        return group
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def convert(self, text):
 | 
				
			||||||
 | 
					        if not text:
 | 
				
			||||||
 | 
					            return ''
 | 
				
			||||||
 | 
					        if self.debug:
 | 
				
			||||||
 | 
					            return RE_COLOR.sub(self._convert_color_debug, text)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return RE_COLOR.sub(self._convert_color, text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def remove(self, text):
 | 
				
			||||||
 | 
					        """Remove colors in a WeeChat string."""
 | 
				
			||||||
 | 
					        if not text:
 | 
				
			||||||
 | 
					            return ''
 | 
				
			||||||
 | 
					        return re.sub(RE_COLOR, '', text)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue