ConversationLayoutManager.py :  » Network » emesene » emesene-1.6.2 » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » emesene 
emesene » emesene 1.6.2 » ConversationLayoutManager.py
# -*- coding: utf-8 -*-

#   This file is part of emesene.
#
#    Emesene is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    emesene is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with emesene; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import os
import re
import time

import paths
import emesenelib.common
from Parser import ConversationDataType


tagRe = re.compile('%(.*?)%')

class ConversationLayoutManager(object):
    ''' This class handles the conversation theming system '''

    def __init__(self, controller):
        self.infos = {}
        self.theme = {}
        self.reset()
        self.setDefault()
        self.controller = controller
        self.config = controller.config
        self.unifiedParser = controller.unifiedParser

    def reset(self):
        ''' Resets the theme '''
        self.infos['name'] = ''
        self.infos['description'] = ''
        self.infos['author'] = ''
        self.infos['website'] = ''
        self.theme['incoming'] = ''
        self.theme['consecutive_incoming'] = ''
        self.theme['offline_incoming'] = ''
        self.theme['outgoing'] = ''
        self.theme['consecutive_outgoing'] = ''
        self.theme['information'] = ''
        self.theme['error'] = ''

    def setValue(self, key, value):
        ''' Sets a key according to the given value '''
        if key in self.theme.keys():
            self.theme[key] = value
        elif key in self.infos.keys():
            self.infos[key] = value
        else:
            emesenelib.common.debug(key + ' is not a valid property for a conversation layout !')

    def resolveValue(self):
        ''' Resolve shortcut like "incoming=outgoing" '''
        for key, value in self.theme.iteritems():
            if value in self.theme.keys():
                self.theme[key] = self.theme[value]

    def setDefault(self):
        ''' Sets the default theme (you should use that when a load fails) '''
        self.theme['incoming'] = '<span style="font-weight: bold;">%nick% says :</span><br/>    [%h%:%m%:%s%] %formattedmessage%<br/>'
        self.theme['consecutive_incoming'] = '    [%h%:%m%:%s%] %formattedmessage%<br/>'
        self.theme['offline_incoming'] = 'incoming'
        self.theme['outgoing'] = 'incoming'
        self.theme['consecutive_outgoing'] = 'consecutive_incoming'
        self.theme['information'] = '    [%h%:%m%:%s%] <span style="font-weight: bold;">%message%</span><br/>'
        self.theme['error'] = '    [%h%:%m%:%s%] <span style="font-weight: bold; color: #FF0000;">%message%</span><br/>'
        self.resolveValue()

    def load(self, name):
        '''Loads a theme, return true on success, false otherwise.
        It seeks the theme in config dir, and then in app dir.
        If the loads fails, the old layout is restored'''
        def doLoad(filename):
            self.reset()
            themefile = None
            try:
                themefile = open(filename, 'r')
                themestring = themefile.read()

                for i in themestring.splitlines():
                    i = i.lstrip()
                    if i != '' and not i.startswith('#'):
                        delim = i.find('=')
                        key = i[:delim].lower()
                        value = i[delim+1:]
                        self.setValue(key, value)

                self.resolveValue()
                themefile.close()

                if not self.isValid():
                    return False
                else:
                    return True

            except:
                if themefile:
                    themefile.close()
                return False

        oldInfos = self.infos
        oldTheme = self.theme

        filename = paths.CONVTHEMES_HOME_PATH + os.sep + name + os.sep + 'theme'
        if not os.path.exists(filename):
            filename = paths.CONVTHEMES_SYSTEM_WIDE_PATH + os.sep + name + \
                os.sep + 'theme'

        if os.path.exists(filename):
            success = doLoad(filename)
        else:
            success = False

        if not success:
            self.infos = oldInfos
            self.theme = oldTheme

        return success

    def isValid(self):
        ''' Checks if the theme is valid '''
        for value in self.theme.values():
            if value == None or value in self.theme.keys():
                return False
        return True

    def listAvailableThemes(self):
        ''' Lists all available and valid themes and return a list '''
        conversationLayout = ConversationLayoutManager(self.controller)
        validThemesList = []

        try:
            homethemes = os.listdir(paths.CONVTHEMES_HOME_PATH)
        except OSError:
            homethemes = []
        try:
            globalthemes = os.listdir(paths.CONVTHEMES_SYSTEM_WIDE_PATH)
        except OSError:
            globalthemes = []

        for currentTheme in homethemes + globalthemes:
            if conversationLayout.load(currentTheme):
                validThemesList.append(currentTheme)

        return validThemesList

    def layout(self, username, message, format, conversation, type, timestamp, \
               ink=False, p4c=False):
        ''' Returns HTML code according to the the current theme '''
        if type not in self.theme.keys():
            return ''

        switchboard = conversation.switchboard

        if not ink:
            messageDataObject = self.unifiedParser.getParser(message, ConversationDataType)
            messageDataObject.setConversation(conversation)
            messageDataObject.setUser(username)

            message = messageDataObject.get(smileys=self.config.user['parseSmilies'])

            message = message.replace('\n', '<br/>')
        else:
            if os.name == 'posix':
                message = '<img src="file://%s" alt="Ink message" />' % message
            else:
                message = '<img src="file://localhost/%s" alt="Ink message" />' % message

        arguments = {}

        # Fills nick
        arguments['nick'] = ''
        if username:
            if username.find("@") == -1: #if it's not an email
                arguments['nick'] = username
            else: #may catch nicknames with the char "@"
                arguments['nick'] = self.controller.msn.getUserDisplayName(username)

        # prevent lowercasing nick when an oim is received
        #if type == 'offline_incoming' and username.find("@") != -1:
        #    arguments['nick'] = username

        # Fills email
        arguments['email'] = username
        
        # Fills message
        arguments['message'] = message

        # Fills avatar
        arguments['avatar'] = ''
        if type == 'outgoing' or type == 'consecutive_outgoing':
            arguments['avatar'] = self.controller.avatar.getImagePath()
        elif type == 'incoming' or type == 'consecutive_incoming':
            arguments['avatar'] = self.controller.msn.cacheDir + os.sep + \
                username.split('@')[0] + '.tmp'

        # Fills (?) timestamp
        arguments['timestamp'] = timestamp

        # Layout
        if format is None:
            parser = LayoutTagParser(self, arguments, self.getCssStyle(), type)
        else:
            parser = LayoutTagParser(self, arguments, format, type)

        result = tagRe.sub(parser.sub, self.theme[type])

        return '<span><span style="font-size: %spt;">%s</span></span>' % \
               (self.config.user['fontSize'], result)

    def getPreview(self):
        ''' Returns a preview of the layout '''
        preview = ''
        arguments = {}
        userStyle = self.getCssStyle()

        # Fills arguments with faked ones
        # First message
        arguments['nick'] = self.controller.msn.nick
        arguments['email'] = 'youremail@hotmail.com'
        arguments['message'] = _('This is an outgoing message')
        arguments['avatar'] = self.controller.avatar.getImagePath()
        arguments['timestamp'] = time.time()
        parser = LayoutTagParser(self, arguments, userStyle, 'outgoing')
        preview += tagRe.sub(parser.sub, self.theme['outgoing'])

        # Second message
        arguments['message'] = _('This is a consecutive outgoing message')
        parser = LayoutTagParser(self, arguments, userStyle, 'consecutive_outgoing')
        preview += tagRe.sub(parser.sub, self.theme['consecutive_outgoing'])

        # Third message
        arguments['nick'] = 'John Doe'
        arguments['email'] = 'john_doe@hotmail.com'
        arguments['message'] = _('This is an incoming message')
        # TODO : have an example picture
        arguments['avatar'] = self.controller.avatar.getImagePath()
        parser = LayoutTagParser(self, arguments, None, 'incoming')
        preview += tagRe.sub(parser.sub, self.theme['incoming'])

        # Fourth message
        arguments['message'] = _('This is a consecutive incoming message')
        parser = LayoutTagParser(self, arguments, None, 'consecutive_incoming')
        preview += tagRe.sub(parser.sub, self.theme['consecutive_incoming'])

        # Information message
        arguments['message'] = _('This is an information message')
        parser = LayoutTagParser(self, arguments, None, 'information')
        preview += tagRe.sub(parser.sub, self.theme['information'])

        # Fourth message
        arguments['message'] = _('This is an error message')
        parser = LayoutTagParser(self, arguments, None, 'error')
        preview += tagRe.sub(parser.sub, self.theme['error'])

        return '<span><span style="font-size: %spt;">%s</span></span>' % \
               (self.config.user['fontSize'], preview)

    def getCssStyle(self):
        '''return the css style of the user'''

        style = ''

        if self.config.user['fontBold']:
            style += 'font-weight: bold;'

        if self.config.user['fontItalic']:
            style += 'font-style: italic;'

        if self.config.user['fontUnderline']:
            if self.config.user['fontStrike']:
                style += 'text-decoration: underline line-through;'
            else:
                style += 'text-decoration: underline;'
        elif self.config.user['fontStrike']:
            style += 'text-decoration: line-through;'

        style += 'font-size: ' + str(self.config.user['fontSize']) + 'pt;'
        style += 'color: ' + str(self.config.user['fontColor']) + ';'
        style += 'font-family: ' + str(self.config.user['fontFace']) + ';'

        return style

    def getName(self):
        return self.infos['name']

    def getDescription(self):
        return self.infos['description']

    def getAuthor(self):
        return self.infos['author']

    def getWebsite(self):
        return self.infos['website']

class LayoutTagParser:
    '''thread-safe environment to parse layout tags'''

    def __init__(self, parent, arguments, format, type):
        self.parent = parent
        self.arguments = arguments
        self.format = format
        self.type = type

        self.controller = parent.controller
        self.config = parent.controller.config
        self.unifiedParser = parent.unifiedParser

    def sub(self, data):
        ''' Called by re.sub for each tag found '''
        tag = data.groups()[0].lower()

        if tag == 'nick':
            nick = self.arguments['nick']

            nickDataObject = self.unifiedParser.getParser(nick, ConversationDataType)
            nick = nickDataObject.get(urls=False, smileys=self.config.user['parseSmilies'])

            return nick

        elif tag == 'message' or \
             (self.config.user['disableFormat'] and tag == 'formattedmessage'):
            return self.arguments['message']

        elif tag == 'formattedmessage':
            message = self.arguments['message']
            return '<span style="%s">%s</span>' % (self.format, message)

        elif tag == 'h':
            return time.strftime('%H', time.localtime(self.arguments['timestamp']))

        elif tag == 'm':
            return time.strftime('%M', time.localtime(self.arguments['timestamp']))

        elif tag == 's':
            return time.strftime('%S', time.localtime(self.arguments['timestamp']))

        elif tag == 'date':
            return time.strftime('%Ex', time.localtime(self.arguments['timestamp']))

        elif tag == 'avatar':
            return '<img src="file://' + self.arguments['avatar'] + '"/>'

        elif tag == 'says':
            return _('says')
            
        elif tag == 'said':
            return _('said')
          
        elif tag == 'offline':
            return _('Offline message')

        elif tag == 'email':
            return self.arguments['email']

        else:
            return data.groups()[0]

    def extractArgument(self, tag):
        ''' Retrieves arguments from a tag '''
        start = tag.find('(')+1
        end = tag.find(')')
        arglist = tag[start:end].replace(' ', '')
        return arglist.split(',')

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.