~ubuntu-branches/ubuntu/oneiric/emesene/oneiric

« back to all changes in this revision

Viewing changes to emesene/gui/base/AdiumTheme.py

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2011-03-03 14:49:13 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20110303144913-0adl9cmw2s35lvzo
Tags: 2.0~git20110303-0ubuntu1
* New upstream git revision (LP: #728469).
* Remove debian/watch, debian/emesene.xpm, debian/install and
  debian/README.source files.
* Remove 21_svn2451_fix_avatar and 20_dont_build_own_libmimic patches.
* debian/control: modify python to python (>= 2.5) in Build-Depends field.
* debian/control: remove python-libmimic from Recommends field.
* debian/control: modify python-gtk2 (>= 2.10) to python-gtk2 (>= 2.12) in
  Depends field.
* debian/control: add python-appindicator and python-xmpp to Recommends
  field.
* debian/control: add python-papyon (>= 0.5.4) and python-webkit to Depends
  field.
* debian/control: update Description field.
* debian/control: add python-setuptools to Build-Depends field.
* debian/control: move python-dbus and python-notify to Depends field.
* Update debian/copyright file.
* Update debian/links file.
* debian/menu: update description field.
* Bump Standards-Version to 3.9.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
'''a module that contains a class that describes a adium theme'''
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
#    This file is part of emesene.
 
5
#
 
6
#    emesene is free software; you can redistribute it and/or modify
 
7
#    it under the terms of the GNU General Public License as published by
 
8
#    the Free Software Foundation; either version 3 of the License, or
 
9
#    (at your option) any later version.
 
10
#
 
11
#    emesene is distributed in the hope that it will be useful,
 
12
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
#    GNU General Public License for more details.
 
15
#
 
16
#    You should have received a copy of the GNU General Public License
 
17
#    along with emesene; if not, write to the Free Software
 
18
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 
 
20
import re
 
21
import os
 
22
import time, calendar
 
23
import datetime
 
24
import xml.sax.saxutils
 
25
 
 
26
import parsers
 
27
import MarkupParser
 
28
 
 
29
class AdiumTheme(object):
 
30
    '''a class that contains information of a adium theme
 
31
    '''
 
32
 
 
33
    def __init__(self, path, timefmt):
 
34
        '''constructor
 
35
 
 
36
        get information from the theme located in path
 
37
        '''
 
38
        self.timefmt        = timefmt
 
39
        self.path           = None
 
40
        self.resources_path = None
 
41
        self.incoming_path  = None
 
42
        self.outgoing_path  = None
 
43
        self.content        = None
 
44
        self.incoming       = None
 
45
        self.incoming_next  = None
 
46
        self.outgoing       = None
 
47
        self.outgoing_next  = None
 
48
        self.info           = None
 
49
 
 
50
        self.load_information(path)
 
51
 
 
52
    def load_information(self, path):
 
53
        '''load the information of the theme on path
 
54
        '''
 
55
        self.path = path
 
56
 
 
57
        info_file = file(os.path.join(path, 'Contents', 'Info.plist'))
 
58
        self.info = parsers.Plist(info_file).info
 
59
 
 
60
        self.resources_path = os.path.join(path, 'Contents', 'Resources')
 
61
        self.incoming_path = os.path.join(self.resources_path, 'Incoming')
 
62
        self.outgoing_path = os.path.join(self.resources_path, 'Outgoing')
 
63
 
 
64
        self.content = read_file(self.resources_path, 'Content.html')
 
65
 
 
66
        self.incoming = read_file(self.incoming_path, 'Content.html')
 
67
        self.incoming_next = read_file(self.incoming_path,
 
68
                'NextContent.html')
 
69
 
 
70
        self.outgoing = read_file(self.outgoing_path, 'Content.html')
 
71
        self.outgoing_next = read_file(self.outgoing_path,
 
72
                'NextContent.html')
 
73
 
 
74
    def format_incoming(self, msg, style=None, cedict={}, cedir=None):
 
75
        '''return a string containing the template for the incoming message
 
76
        with the vars replaced
 
77
        '''
 
78
        # fallback madness, some repetition but well..
 
79
        if not msg.first:
 
80
            if self.incoming_next is None:
 
81
                if self.incoming is None:
 
82
                    template = self.content
 
83
                else:
 
84
                    template = self.incoming
 
85
            else:
 
86
                template = self.incoming_next
 
87
        elif self.incoming is None:
 
88
            template = self.content
 
89
        else:
 
90
            template = self.incoming
 
91
 
 
92
        return self.replace(template, msg, style, cedict, cedir)
 
93
 
 
94
    def format_outgoing(self, msg, style=None, cedict={}, cedir=None):
 
95
        '''return a string containing the template for the outgoing message
 
96
        with the vars replaced
 
97
        '''
 
98
        # fallback madness, some repetition but well..
 
99
        if not msg.first:
 
100
            if self.outgoing_next is None:
 
101
                if self.outgoing is None:
 
102
                    if self.incoming is None:
 
103
                        template = self.content
 
104
                    else:
 
105
                        template = self.incoming
 
106
                else:
 
107
                    template = self.outgoing
 
108
            else:
 
109
                template = self.outgoing_next
 
110
        elif self.outgoing is None:
 
111
            if self.incoming is None:
 
112
                template = self.content
 
113
            else:
 
114
                template = self.incoming
 
115
        else:
 
116
            template = self.outgoing
 
117
 
 
118
        return self.replace(template, msg, style, cedict, cedir)
 
119
 
 
120
    def replace(self, template, msg, style=None, cedict={}, cedir=None):
 
121
        '''replace the variables on template for the values on msg
 
122
        '''
 
123
 
 
124
        msgtext = MarkupParser.replace_emotes(escape(msg.message), cedict, cedir, msg.sender)
 
125
        msgtext = MarkupParser.urlify(msgtext)
 
126
 
 
127
        if style is not None:
 
128
            msgtext = style_message(msgtext, style)
 
129
 
 
130
        template = template.replace('%sender%', escape(msg.alias))
 
131
        template = template.replace('%senderScreenName%', escape(msg.sender))
 
132
        template = template.replace('%senderDisplayName%',
 
133
            escape(msg.display_name))
 
134
        template = template.replace('%userIconPath%', escape(msg.image_path))
 
135
        template = template.replace('%senderStatusIcon%',
 
136
            escape(msg.status_path))
 
137
        template = template.replace('%messageDirection%',
 
138
            escape(msg.direction))
 
139
        template = template.replace('%message%', msgtext)
 
140
 
 
141
        if msg.timestamp is None:
 
142
            template = template.replace('%time%',
 
143
                escape(time.strftime(self.timefmt)))
 
144
        else:
 
145
            def utc_to_local(t):
 
146
                secs = calendar.timegm(t)
 
147
                return time.localtime(secs)
 
148
            l_time = utc_to_local(msg.timestamp.timetuple()) #time.struct_time
 
149
            d_time = datetime.datetime.fromtimestamp(time.mktime(l_time))
 
150
            template = template.replace('%time%', 
 
151
                escape(d_time.strftime('%x %X')))
 
152
 
 
153
        template = re.sub("%time{(.*?)}%", replace_time, template)
 
154
        template = template.replace('%shortTime%',
 
155
            escape(time.strftime("%H:%M")))
 
156
        template = template.replace('%service%', escape(msg.service))
 
157
        template = template.replace('%messageClasses%', escape(msg.classes))
 
158
        template = template.replace('%status%', escape(msg.status))
 
159
 
 
160
        return template.replace('\n', '')
 
161
 
 
162
    def replace_header_or_footer(self, template, source, target,
 
163
            target_display, source_img, target_img):
 
164
        '''replace the variables on template for the parameters
 
165
        '''
 
166
        template = template.replace('%chatName%', escape(target))
 
167
        template = template.replace('%sourceName%', escape(source))
 
168
        template = template.replace('%destinationName%', escape(target))
 
169
        template = template.replace('%destinationDisplayName%',
 
170
            escape(target_display))
 
171
        template = template.replace('%incomingIconPath%', escape(target_img))
 
172
        template = template.replace('%outgoingIconPath%', escape(source_img))
 
173
        template = template.replace('%timeOpened%',
 
174
            escape(time.strftime("%H:%M")))
 
175
        # TODO: use the format inside the {}
 
176
        template = re.sub("%timeOpened{.*?}%", escape(time.strftime("%H:%M")),
 
177
            template)
 
178
 
 
179
        return template
 
180
 
 
181
    def get_body(self, source, target, target_display, source_img, target_img):
 
182
        '''return the template to put as html content
 
183
        '''
 
184
        template = read_file(os.path.join("gui", "base", "template.html"))
 
185
        css_path = "file://" + os.path.join(self.resources_path, "main.css")
 
186
        variant_name = self.info.get('DefaultVariant', None)
 
187
        template = template.replace("%@", "file://" + self.resources_path + "/", 1)
 
188
        template = template.replace("%@", css_path, 1)
 
189
 
 
190
        if variant_name is not None:
 
191
            variant_css_path = "file://" + os.path.join(self.resources_path,
 
192
                    "Variants", variant_name + ".css")
 
193
            variant_tag = '<style id="mainStyle" type="text/css"' + \
 
194
                'media="screen,print">  @import url( "' + variant_css_path + '" ); </style>'
 
195
        else:
 
196
            variant_tag = ""
 
197
 
 
198
        template = template.replace("%@", variant_tag, 1)
 
199
 
 
200
        header = read_file(self.resources_path, 'Header.html') or ""
 
201
 
 
202
        if header:
 
203
            header = self.replace_header_or_footer(header, source, target,
 
204
                    target_display, source_img, target_img)
 
205
 
 
206
        template = template.replace("%@", header, 1)
 
207
        footer = read_file(self.resources_path, 'Footer.html') or ""
 
208
 
 
209
        if footer:
 
210
            footer = self.replace_header_or_footer(footer, source, target,
 
211
                    target_display, source_img, target_img)
 
212
 
 
213
        template = template.replace("%@", footer, 1)
 
214
 
 
215
        return template
 
216
 
 
217
def read_file(*args):
 
218
    '''read file if exists and is readable, return None otherwise
 
219
    '''
 
220
    path = os.path.join(*args)
 
221
    if os.access(path, os.R_OK):
 
222
        return file(path).read()
 
223
 
 
224
    return None
 
225
 
 
226
__dic = {
 
227
    '\"': '&quot;',
 
228
    '\'': '&apos;',
 
229
    '\\': '\\\\',
 
230
    '\r\n': '<br>', #windows
 
231
    '\r': '<br>', #osx
 
232
    '\n': '<br>' #linux
 
233
}
 
234
 
 
235
__dic_inv = {
 
236
    '&quot;' :'\"',
 
237
    '&apos;' :'\'',
 
238
    '<br>':    '\n'
 
239
}
 
240
 
 
241
def escape(string_):
 
242
    '''replace the values on dic keys with the values'''
 
243
    return xml.sax.saxutils.escape(string_, __dic)
 
244
 
 
245
def unescape(string_):
 
246
    '''replace the values on dic_inv keys with the values'''
 
247
    return xml.sax.saxutils.unescape(string_, __dic_inv)
 
248
 
 
249
def replace_time(match):
 
250
    '''replace the format of the time to it's value'''
 
251
    return time.strftime(match.groups()[0])
 
252
 
 
253
def style_message(msgtext, style):
 
254
    '''add html markupt to msgtext to format the style of the message'''
 
255
    return '<span style="%s">%s</span>' % (style.to_css(), msgtext)
 
256