...
 
Commits (49)
# coding=utf-8
emoticons = {
'smile.png': [':-)', ':)'],
'coolglasses.png': ['B-)', '(H)'],
'wink.gif': [';-)', ';)'],
'biggrin.png': [':-D', ':D'],
'unhappy.png': [':-(', ':('],
'cry.gif': [":'-(", ":'(", ';-(', ';(', ";'-("],
'frowning.png': [':-/', ':/', ':-\\', ':\\', ':-S', ':S'],
'blush.png': [':-$', ':$'],
'angry.png': [':-@', ':@'],
'bat.gif': [':-[', ':['],
'kiss.png': [':-{}', ':-*', ':*', '(K)'],
'stare.png': [':-|', ':|'],
'devil.png': [']:->', '>:-)', '>:)', '(6)'],
'tongue.png': [':-P', ':P', ':-þ', ':þ'],
'oh.png': ['=-O', ':-O', ':O'],
'heart.png': ['<3', '(L)', '*IN LOVE*'],
'pussy.png': ['(@)'],
'cuffs.png': ['(%)'],
'moon.png': ['(S)'],
'lamp.png': ['(I)'],
'music.png': ['(8)'],
'beer.png': ['(B)', '*DRINK*'],
'brflower.png': ['(W)'],
'boy.png': ['(Z)'],
'girl.png': ['(X)'],
'mail.png': ['(E)'],
'thumbdown.png': ['(N)'],
'photo.png': ['(P)'],
'thumbup.png': ['(Y)', '*THUMBS UP*'],
'hugleft.png': ['(})'],
'brheart.png': ['</3', '(U)'],
'flower.png': ['@}->--', '(F)'],
'drink.png': ['(D)'],
'phone.png': ['(T)'],
'coffee.png': ['(C)'],
'hugright.png': ['({)'],
'star.png': ['(*)'],
'rainbow.png': ['(R)'],
'cigarette.gif': ['(ci)'],
'cake.gif': ['(^)'],
'dontknow.gif': [':^)'],
'eyeroll.gif': ['8-)'],
'lightning.gif': ['(li)'],
'party.gif': ['<:o)'],
'sleepy.gif': ['|-)'],
'think.gif': ['*-)'],
'puke.gif': [':-!'],
'smile.png': [':-)', ':)'],
'coolglasses.png': ['B-)', '(H)'],
'wink.gif': [';-)', ';)'],
'biggrin.png': [':-D', ':D'],
'unhappy.png': [':-(', ':('],
'cry.gif': [":'-(", ":'(", ';-(', ';(', ";'-("],
'frowning.png': [':-/', ':/', ':-\\', ':\\', ':-S', ':S'],
'blush.png': [':-$', ':$'],
'angry.png': [':-@', ':@'],
'bat.gif': [':-[', ':['],
'kiss.png': [':-{}', ':-*', ':*', '(K)'],
'stare.png': [':-|', ':|'],
'devil.png': [']:->', '>:-)', '>:)', '(6)'],
'tongue.png': [':-P', ':P', ':-þ', ':þ'],
'oh.png': ['=-O', ':-O', ':O'],
'heart.png': ['<3', '(L)', '*IN LOVE*'],
'pussy.png': ['(@)'],
'cuffs.png': ['(%)'],
'moon.png': ['(S)'],
'lamp.png': ['(I)'],
'music.png': ['(8)'],
'beer.png': ['(B)', '*DRINK*'],
'brflower.png': ['(W)'],
'boy.png': ['(Z)'],
'girl.png': ['(X)'],
'mail.png': ['(E)'],
'thumbdown.png': ['(N)'],
'photo.png': ['(P)'],
'thumbup.png': ['(Y)', '*THUMBS UP*'],
'hugleft.png': ['(})'],
'brheart.png': ['</3', '(U)'],
'flower.png': ['@}->--', '(F)'],
'drink.png': ['(D)'],
'phone.png': ['(T)'],
'coffee.png': ['(C)'],
'hugright.png': ['({)'],
'star.png': ['(*)'],
'rainbow.png': ['(R)'],
'cigarette.gif': ['(ci)'],
'cake.gif': ['(^)'],
'dontknow.gif': [':^)'],
'eyeroll.gif': ['8-)'],
'lightning.gif': ['(li)'],
'party.gif': ['<:o)'],
'sleepy.gif': ['|-)'],
'think.gif': ['*-)'],
'puke.gif': [':-!'],
}
# vim: se ts=3:
# coding=utf-8
emoticons = {
'smile.png': [':-)', ':)'],
'coolglasses.png': ['8-)', 'B-)', '(H)'],
'wink.png': [';-)', ';)'],
'biggrin.png': [':-D', ':D'],
'unhappy.png': [':-(', ':('],
'cry.png': [":'-(", ":'(", ';-(', ';(', ";'-("],
'frowning.png': [':-/', ':/', ':-\\', ':\\', ':-S', ':S'],
'blush.png': [':-$', ':$'],
'angry.png': [':-@', ':@'],
'bat.png': [':-[', ':['],
'kiss.png': [':-{}', ':-*', ':*', '(K)'],
'stare.png': [':-|', ':|'],
'devil.png': [']:->', '>:-)', '>:)', '(6)'],
'tongue.png': [':-P', ':P', ':-þ', ':þ'],
'oh.png': ['=-O', ':-O', ':O'],
'heart.png': ['<3', '(L)', '*IN LOVE*'],
'lion.png': [':3', '>:3'],
'pussy.png': ['(@)', '=^.^='],
'cuffs.png': ['(%)'],
'moon.png': ['(S)'],
'lamp.png': ['(I)'],
'music.png': ['(8)'],
'beer.png': ['(B)', '*DRINK*'],
'brflower.png': ['(W)'],
'boy.png': ['(Z)'],
'girl.png': ['(X)'],
'mail.png': ['(E)'],
'thumbdown.png': ['(N)'],
'photo.png': ['(P)'],
'thumbup.png': ['(Y)', '*THUMBS UP*'],
'hugleft.png': ['(})'],
'brheart.png': ['</3', '(U)'],
'flower.png': ['@}->--', '(F)'],
'drink.png': ['(D)'],
'phone.png': ['(T)'],
'coffee.png': ['(C)'],
'hugright.png': ['({)'],
'star.png': ['(*)'],
'rainbow.png': ['(R)'],
'puke.png': [':-!'],
'smile.png': [':-)', ':)'],
'coolglasses.png': ['8-)', 'B-)', '(H)'],
'wink.png': [';-)', ';)'],
'biggrin.png': [':-D', ':D'],
'unhappy.png': [':-(', ':('],
'cry.png': [":'-(", ":'(", ';-(', ';(', ";'-("],
'frowning.png': [':-/', ':/', ':-\\', ':\\', ':-S', ':S'],
'blush.png': [':-$', ':$'],
'angry.png': [':-@', ':@'],
'bat.png': [':-[', ':['],
'kiss.png': [':-{}', ':-*', ':*', '(K)'],
'stare.png': [':-|', ':|'],
'devil.png': [']:->', '>:-)', '>:)', '(6)'],
'tongue.png': [':-P', ':P', ':-þ', ':þ'],
'oh.png': ['=-O', ':-O', ':O'],
'heart.png': ['<3', '(L)', '*IN LOVE*'],
'lion.png': [':3', '>:3'],
'pussy.png': ['(@)', '=^.^='],
'cuffs.png': ['(%)'],
'moon.png': ['(S)'],
'lamp.png': ['(I)'],
'music.png': ['(8)'],
'beer.png': ['(B)', '*DRINK*'],
'brflower.png': ['(W)'],
'boy.png': ['(Z)'],
'girl.png': ['(X)'],
'mail.png': ['(E)'],
'thumbdown.png': ['(N)'],
'photo.png': ['(P)'],
'thumbup.png': ['(Y)', '*THUMBS UP*'],
'hugleft.png': ['(})'],
'brheart.png': ['</3', '(U)'],
'flower.png': ['@}->--', '(F)'],
'drink.png': ['(D)'],
'phone.png': ['(T)'],
'coffee.png': ['(C)'],
'hugright.png': ['({)'],
'star.png': ['(*)'],
'rainbow.png': ['(R)'],
'puke.png': [':-!'],
}
# vim: se ts=3:
# coding=utf-8
emoticons = {
'smile.png': [':-)', ':)'],
'coolglasses.png': ['8-)', 'B-)', '(H)'],
'wink.png': [';-)', ';)'],
'biggrin.png': [':-D', ':D'],
'unhappy.png': [':-(', ':('],
'cry.png': [":'-(", ":'(", ';-(', ';(', ";'-("],
'frowning.png': [':-/', ':/', ':-\\', ':\\', ':-S', ':S'],
'blush.png': [':-$', ':$'],
'angry.png': [':-@', ':@'],
'bat.png': [':-[', ':['],
'kiss.png': [':-{}', ':-*', ':*', '(K)'],
'stare.png': [':-|', ':|'],
'devil.png': [']:->', '>:-)', '>:)', '(6)'],
'tongue.png': [':-P', ':P', ':-þ', ':þ'],
'oh.png': ['=-O', ':-O', ':O'],
'heart.png': ['<3', '(L)', '*IN LOVE*'],
'lion.png': [':3', '>:3'],
'pussy.png': ['(@)', '=^.^='],
'cuffs.png': ['(%)'],
'moon.png': ['(S)'],
'lamp.png': ['(I)'],
'music.png': ['(8)'],
'beer.png': ['(B)', '*DRINK*'],
'brflower.png': ['(W)'],
'boy.png': ['(Z)'],
'girl.png': ['(X)'],
'mail.png': ['(E)'],
'thumbdown.png': ['(N)'],
'photo.png': ['(P)'],
'thumbup.png': ['(Y)', '*THUMBS UP*'],
'hugleft.png': ['(})'],
'brheart.png': ['</3', '(U)'],
'flower.png': ['@}->--', '(F)'],
'drink.png': ['(D)'],
'phone.png': ['(T)'],
'coffee.png': ['(C)'],
'hugright.png': ['({)'],
'star.png': ['(*)'],
'rainbow.png': ['(R)'],
'puke.png': [':-!'],
'smile.png': [':-)', ':)'],
'coolglasses.png': ['8-)', 'B-)', '(H)'],
'wink.png': [';-)', ';)'],
'biggrin.png': [':-D', ':D'],
'unhappy.png': [':-(', ':('],
'cry.png': [":'-(", ":'(", ';-(', ';(', ";'-("],
'frowning.png': [':-/', ':/', ':-\\', ':\\', ':-S', ':S'],
'blush.png': [':-$', ':$'],
'angry.png': [':-@', ':@'],
'bat.png': [':-[', ':['],
'kiss.png': [':-{}', ':-*', ':*', '(K)'],
'stare.png': [':-|', ':|'],
'devil.png': [']:->', '>:-)', '>:)', '(6)'],
'tongue.png': [':-P', ':P', ':-þ', ':þ'],
'oh.png': ['=-O', ':-O', ':O'],
'heart.png': ['<3', '(L)', '*IN LOVE*'],
'lion.png': [':3', '>:3'],
'pussy.png': ['(@)', '=^.^='],
'cuffs.png': ['(%)'],
'moon.png': ['(S)'],
'lamp.png': ['(I)'],
'music.png': ['(8)'],
'beer.png': ['(B)', '*DRINK*'],
'brflower.png': ['(W)'],
'boy.png': ['(Z)'],
'girl.png': ['(X)'],
'mail.png': ['(E)'],
'thumbdown.png': ['(N)'],
'photo.png': ['(P)'],
'thumbup.png': ['(Y)', '*THUMBS UP*'],
'hugleft.png': ['(})'],
'brheart.png': ['</3', '(U)'],
'flower.png': ['@}->--', '(F)'],
'drink.png': ['(D)'],
'phone.png': ['(T)'],
'coffee.png': ['(C)'],
'hugright.png': ['({)'],
'star.png': ['(*)'],
'rainbow.png': ['(R)'],
'puke.png': [':-!'],
}
# vim: se ts=3:
This diff is collapsed.
<?xml version="1.0"?>
<glade-interface>
<!-- interface-requires gtk+ 2.16 -->
<!-- interface-naming-policy project-wide -->
<widget class="GtkWindow" id="window1">
<child>
<widget class="GtkHBox" id="whiteboard_hbox">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<placeholder/>
</child>
<child>
<widget class="GtkVButtonBox" id="vbuttonbox1">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="spacing">6</property>
<property name="layout_style">start</property>
<child>
<widget class="GtkButton" id="brush_button">
<property name="label" translatable="yes">Brush Tool</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_brush_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="oval_button">
<property name="label" translatable="yes">Oval Tool</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_oval_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="line_button">
<property name="label" translatable="yes">Line Tool</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_line_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="delete_button">
<property name="label" translatable="yes">Delete Tool
</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_delete_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="clear_button">
<property name="label" translatable="yes">Clear Canvas</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_clear_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="export_button">
<property name="label" translatable="yes">Export XML</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_export_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
</packing>
</child>
<child>
<widget class="GtkHScale" id="size_scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="format_value" handler="on_size_scale_format_value"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">6</property>
<property name="secondary">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="fg_color_hbox">
<property name="visible">True</property>
<child>
<widget class="GtkLabel" id="fg_color_label">
<property name="visible">True</property>
<property name="xpad">1</property>
<property name="ypad">1</property>
<property name="label" translatable="yes">Foreground
Color:</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="fg_color_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="color">#000000000000</property>
<signal name="color_set" handler="on_fg_color_button_color_set"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">7</property>
<property name="secondary">True</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
......@@ -5,10 +5,7 @@ import os
import sys
if os.getcwd().endswith('dev'):
os.chdir('../../src/') # we were in scripts/dev
os.chdir('../../src/') # we were in scripts/dev
os.system('pychecker --limit 10000 --no-shadowbuiltin *.py &> /tmp/pychecker-gajim.log')
os.system('$EDITOR /tmp/pychecker-gajim.log')
# vim: se ts=3:
This diff is collapsed.
......@@ -52,15 +52,16 @@ if 'gtk' in os.listdir('.'):
opts = {
'py2exe': {
# ConfigParser,UserString,roman are needed for docutils
'includes': 'pango,atk,gobject,cairo,pangocairo,gtk.keysyms,encodings,encodings.*,ConfigParser,UserString',
'includes': ('pango,atk,gobject,cairo,pangocairo,gtk.keysyms,'
'encodings,encodings.*,ConfigParser,UserString'),
'dll_excludes': [
'iconv.dll','intl.dll','libatk-1.0-0.dll',
'libgdk_pixbuf-2.0-0.dll','libgdk-win32-2.0-0.dll',
'libglib-2.0-0.dll','libgmodule-2.0-0.dll',
'libgobject-2.0-0.dll','libgthread-2.0-0.dll',
'libgtk-win32-2.0-0.dll','libpango-1.0-0.dll',
'libpangowin32-1.0-0.dll','libcairo-2.dll',
'libpangocairo-1.0-0.dll','libpangoft2-1.0-0.dll',
'iconv.dll', 'intl.dll', 'libatk-1.0-0.dll',
'libgdk_pixbuf-2.0-0.dll', 'libgdk-win32-2.0-0.dll',
'libglib-2.0-0.dll', 'libgmodule-2.0-0.dll',
'libgobject-2.0-0.dll', 'libgthread-2.0-0.dll',
'libgtk-win32-2.0-0.dll', 'libpango-1.0-0.dll',
'libpangowin32-1.0-0.dll', 'libcairo-2.dll',
'libpangocairo-1.0-0.dll', 'libpangoft2-1.0-0.dll',
],
'excludes': [
'docutils'
......@@ -70,22 +71,17 @@ opts = {
setup(
name = 'Gajim',
version = '0.12.1',
description = 'A full featured Jabber client',
author = 'Gajim Development Team',
url = 'http://www.gajim.org/',
download_url = 'http://www.gajim.org/downloads.php',
license = 'GPL',
windows = [{'script': 'src/gajim.py',
'icon_resources': [(1, 'data/pixmaps/gajim.ico')]},
{'script': 'src/history_manager.py',
'icon_resources': [(1, 'data/pixmaps/gajim.ico')]}],
name='Gajim',
version='0.12.1',
description='A full featured Jabber client',
author='Gajim Development Team',
url='http://www.gajim.org/',
download_url='http://www.gajim.org/downloads.php',
license='GPL',
windows=[{'script': 'src/gajim.py',
'icon_resources': [(1, 'data/pixmaps/gajim.ico')]},
{'script': 'src/history_manager.py',
'icon_resources': [(1, 'data/pixmaps/gajim.ico')]}],
options=opts,
data_files=docutils_files,
)
# vim: se ts=3:
This diff is collapsed.
This diff is collapsed.
......@@ -29,108 +29,106 @@ import gtkgui_helpers
from common import helpers
class AtomWindow:
window = None
entries = []
@classmethod
def newAtomEntry(cls, entry):
''' Queue new entry, open window if there's no one opened. '''
cls.entries.append(entry)
if cls.window is None:
cls.window = AtomWindow()
else:
cls.window.updateCounter()
def __init__(self):
''' Create new window... only if we have anything to show. '''
assert len(self.__class__.entries)>0
self.entry = None # the entry actually displayed
self.xml = gtkgui_helpers.get_glade('atom_entry_window.glade')
self.window = self.xml.get_widget('atom_entry_window')
for name in ('new_entry_label', 'feed_title_label', 'feed_title_eventbox',
'feed_tagline_label', 'entry_title_label', 'entry_title_eventbox',
'last_modified_label', 'close_button', 'next_button'):
self.__dict__[name] = self.xml.get_widget(name)
self.displayNextEntry()
self.xml.signal_autoconnect(self)
self.window.show_all()
self.entry_title_eventbox.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.feed_title_eventbox.add_events(gtk.gdk.BUTTON_PRESS_MASK)
def displayNextEntry(self):
''' Get next entry from the queue and display it in the window. '''
assert len(self.__class__.entries)>0
newentry = self.__class__.entries.pop(0)
# fill the fields
if newentry.feed_link is not None:
self.feed_title_label.set_markup(
u'<span foreground="blue" underline="single">%s</span>' % \
gobject.markup_escape_text(newentry.feed_title))
else:
self.feed_title_label.set_markup(
gobject.markup_escape_text(newentry.feed_title))
self.feed_tagline_label.set_markup(
u'<small>%s</small>' % \
gobject.markup_escape_text(newentry.feed_tagline))
if newentry.uri is not None:
self.entry_title_label.set_markup(
u'<span foreground="blue" underline="single">%s</span>' % \
gobject.markup_escape_text(newentry.title))
else:
self.entry_title_label.set_markup(
gobject.markup_escape_text(newentry.title))
self.last_modified_label.set_text(newentry.updated)
# update the counters
self.updateCounter()
self.entry = newentry
def updateCounter(self):
''' We display number of events on the top of window, sometimes it needs to be
changed...'''
count = len(self.__class__.entries)
# TODO: translate
if count>0:
self.new_entry_label.set_text( \
'You have received new entries (and %(count)d not displayed):' % \
{'count': count})
self.next_button.set_sensitive(True)
else:
self.new_entry_label.set_text('You have received new entry:')
self.next_button.set_sensitive(False)
def on_close_button_clicked(self, widget):
self.window.destroy()
def on_next_button_clicked(self, widget):
self.displayNextEntry()
def on_entry_title_button_press_event(self, widget, event):
#FIXME: make it using special gtk2.10 widget
if event.button == 1: # left click
uri = self.entry.uri
if uri is not None:
helpers.launch_browser_mailer('url', uri)
return True
def on_feed_title_button_press_event(self, widget, event):
#FIXME: make it using special gtk2.10 widget
if event.button == 1: # left click
uri = self.entry.feed_uri
if uri is not None:
helpers.launch_browser_mailer('url', uri)
return True
# vim: se ts=3:
window = None
entries = []
@classmethod
def newAtomEntry(cls, entry):
''' Queue new entry, open window if there's no one opened. '''
cls.entries.append(entry)
if cls.window is None:
cls.window = AtomWindow()
else:
cls.window.updateCounter()
def __init__(self):
''' Create new window... only if we have anything to show. '''
assert len(self.__class__.entries)>0
self.entry = None # the entry actually displayed
self.xml = gtkgui_helpers.get_glade('atom_entry_window.glade')
self.window = self.xml.get_widget('atom_entry_window')
for name in ('new_entry_label', 'feed_title_label', 'feed_title_eventbox',
'feed_tagline_label', 'entry_title_label', 'entry_title_eventbox',
'last_modified_label', 'close_button', 'next_button'):
self.__dict__[name] = self.xml.get_widget(name)
self.displayNextEntry()
self.xml.signal_autoconnect(self)
self.window.show_all()
self.entry_title_eventbox.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.feed_title_eventbox.add_events(gtk.gdk.BUTTON_PRESS_MASK)
def displayNextEntry(self):
''' Get next entry from the queue and display it in the window. '''
assert len(self.__class__.entries)>0
newentry = self.__class__.entries.pop(0)
# fill the fields
if newentry.feed_link is not None:
self.feed_title_label.set_markup(
u'<span foreground="blue" underline="single">%s</span>' % \
gobject.markup_escape_text(newentry.feed_title))
else:
self.feed_title_label.set_markup(
gobject.markup_escape_text(newentry.feed_title))
self.feed_tagline_label.set_markup(
u'<small>%s</small>' % \
gobject.markup_escape_text(newentry.feed_tagline))
if newentry.uri is not None:
self.entry_title_label.set_markup(
u'<span foreground="blue" underline="single">%s</span>' % \
gobject.markup_escape_text(newentry.title))
else:
self.entry_title_label.set_markup(
gobject.markup_escape_text(newentry.title))
self.last_modified_label.set_text(newentry.updated)
# update the counters
self.updateCounter()
self.entry = newentry
def updateCounter(self):
''' We display number of events on the top of window, sometimes it needs to be
changed...'''
count = len(self.__class__.entries)
# TODO: translate
if count>0:
self.new_entry_label.set_text( \
'You have received new entries (and %(count)d not displayed):' % \
{'count': count})
self.next_button.set_sensitive(True)
else:
self.new_entry_label.set_text('You have received new entry:')
self.next_button.set_sensitive(False)
def on_close_button_clicked(self, widget):
self.window.destroy()
def on_next_button_clicked(self, widget):
self.displayNextEntry()
def on_entry_title_button_press_event(self, widget, event):
#FIXME: make it using special gtk2.10 widget
if event.button == 1: # left click
uri = self.entry.uri
if uri is not None:
helpers.launch_browser_mailer('url', uri)
return True
def on_feed_title_button_press_event(self, widget, event):
#FIXME: make it using special gtk2.10 widget
if event.button == 1: # left click
uri = self.entry.feed_uri
if uri is not None:
helpers.launch_browser_mailer('url', uri)
return True
......@@ -27,113 +27,111 @@ import gobject
class CellRendererImage(gtk.GenericCellRenderer):
__gproperties__ = {
'image': (gobject.TYPE_OBJECT, 'Image',
'Image', gobject.PARAM_READWRITE),
}
def __init__(self, col_index, tv_index):
self.__gobject_init__()
self.image = None
self.col_index = col_index
self.tv_index = tv_index
self.iters = {}
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
def do_get_property(self, pspec):
return getattr(self, pspec.name)
def func(self, model, path, iter_, image_tree):
image, tree = image_tree
if model.get_value(iter_, self.tv_index) != image:
return
self.redraw = 1
col = tree.get_column(self.col_index)
cell_area = tree.get_cell_area(path, col)
tree.queue_draw_area(cell_area.x, cell_area.y,
cell_area.width, cell_area.height)
def animation_timeout(self, tree, image):
if image.get_storage_type() != gtk.IMAGE_ANIMATION:
return
self.redraw = 0
iter_ = self.iters[image]
iter_.advance()
model = tree.get_model()
if model:
model.foreach(self.func, (image, tree))
if self.redraw:
gobject.timeout_add(iter_.get_delay_time(),
self.animation_timeout, tree, image)
elif image in self.iters:
del self.iters[image]
def on_render(self, window, widget, background_area, cell_area,
expose_area, flags):
if not self.image:
return
pix_rect = gtk.gdk.Rectangle()
pix_rect.x, pix_rect.y, pix_rect.width, pix_rect.height = \
self.on_get_size(widget, cell_area)
pix_rect.x += cell_area.x
pix_rect.y += cell_area.y
pix_rect.width -= 2 * self.get_property('xpad')
pix_rect.height -= 2 * self.get_property('ypad')
draw_rect = cell_area.intersect(pix_rect)
draw_rect = expose_area.intersect(draw_rect)
if self.image.get_storage_type() == gtk.IMAGE_ANIMATION:
if self.image not in self.iters:
if not isinstance(widget, gtk.TreeView):
return
animation = self.image.get_animation()
iter_ = animation.get_iter()
self.iters[self.image] = iter_
gobject.timeout_add(iter_.get_delay_time(),
self.animation_timeout, widget, self.image)
pix = self.iters[self.image].get_pixbuf()
elif self.image.get_storage_type() == gtk.IMAGE_PIXBUF:
pix = self.image.get_pixbuf()
else:
return
if draw_rect.x < 1:
return
window.draw_pixbuf(widget.style.black_gc, pix,
draw_rect.x - pix_rect.x,
draw_rect.y - pix_rect.y,
draw_rect.x, draw_rect.y,
draw_rect.width, draw_rect.height,
gtk.gdk.RGB_DITHER_NONE, 0, 0)
def on_get_size(self, widget, cell_area):
if not self.image:
return 0, 0, 0, 0
if self.image.get_storage_type() == gtk.IMAGE_ANIMATION:
animation = self.image.get_animation()
pix = animation.get_iter().get_pixbuf()
elif self.image.get_storage_type() == gtk.IMAGE_PIXBUF:
pix = self.image.get_pixbuf()
else:
return 0, 0, 0, 0
pixbuf_width = pix.get_width()
pixbuf_height = pix.get_height()
calc_width = self.get_property('xpad') * 2 + pixbuf_width
calc_height = self.get_property('ypad') * 2 + pixbuf_height
x_offset = 0
y_offset = 0
if cell_area and pixbuf_width > 0 and pixbuf_height > 0:
x_offset = self.get_property('xalign') * \
(cell_area.width - calc_width - \
self.get_property('xpad'))
y_offset = self.get_property('yalign') * \
(cell_area.height - calc_height - \
self.get_property('ypad'))
return x_offset, y_offset, calc_width, calc_height
# vim: se ts=3:
__gproperties__ = {
'image': (gobject.TYPE_OBJECT, 'Image',
'Image', gobject.PARAM_READWRITE),
}
def __init__(self, col_index, tv_index):
self.__gobject_init__()
self.image = None
self.col_index = col_index
self.tv_index = tv_index
self.iters = {}
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
def do_get_property(self, pspec):
return getattr(self, pspec.name)
def func(self, model, path, iter_, image_tree):
image, tree = image_tree
if model.get_value(iter_, self.tv_index) != image:
return
self.redraw = 1
col = tree.get_column(self.col_index)
cell_area = tree.get_cell_area(path, col)
tree.queue_draw_area(cell_area.x, cell_area.y,
cell_area.width, cell_area.height)
def animation_timeout(self, tree, image):
if image.get_storage_type() != gtk.IMAGE_ANIMATION:
return
self.redraw = 0
iter_ = self.iters[image]
iter_.advance()
model = tree.get_model()
if model:
model.foreach(self.func, (image, tree))
if self.redraw:
gobject.timeout_add(iter_.get_delay_time(),
self.animation_timeout, tree, image)
elif image in self.iters:
del self.iters[image]
def on_render(self, window, widget, background_area, cell_area,
expose_area, flags):
if not self.image:
return
pix_rect = gtk.gdk.Rectangle()
pix_rect.x, pix_rect.y, pix_rect.width, pix_rect.height = \
self.on_get_size(widget, cell_area)
pix_rect.x += cell_area.x
pix_rect.y += cell_area.y
pix_rect.width -= 2 * self.get_property('xpad')
pix_rect.height -= 2 * self.get_property('ypad')
draw_rect = cell_area.intersect(pix_rect)
draw_rect = expose_area.intersect(draw_rect)
if self.image.get_storage_type() == gtk.IMAGE_ANIMATION:
if self.image not in self.iters:
if not isinstance(widget, gtk.TreeView):
return
animation = self.image.get_animation()
iter_ = animation.get_iter()
self.iters[self.image] = iter_
gobject.timeout_add(iter_.get_delay_time(),
self.animation_timeout, widget, self.image)
pix = self.iters[self.image].get_pixbuf()
elif self.image.get_storage_type() == gtk.IMAGE_PIXBUF:
pix = self.image.get_pixbuf()
else:
return
if draw_rect.x < 1:
return
window.draw_pixbuf(widget.style.black_gc, pix,
draw_rect.x - pix_rect.x,
draw_rect.y - pix_rect.y,
draw_rect.x, draw_rect.y,
draw_rect.width, draw_rect.height,
gtk.gdk.RGB_DITHER_NONE, 0, 0)
def on_get_size(self, widget, cell_area):
if not self.image:
return 0, 0, 0, 0
if self.image.get_storage_type() == gtk.IMAGE_ANIMATION:
animation = self.image.get_animation()
pix = animation.get_iter().get_pixbuf()
elif self.image.get_storage_type() == gtk.IMAGE_PIXBUF:
pix = self.image.get_pixbuf()
else:
return 0, 0, 0, 0
pixbuf_width = pix.get_width()
pixbuf_height = pix.get_height()
calc_width = self.get_property('xpad') * 2 + pixbuf_width
calc_height = self.get_property('ypad') * 2 + pixbuf_height
x_offset = 0
y_offset = 0
if cell_area and pixbuf_width > 0 and pixbuf_height > 0:
x_offset = self.get_property('xalign') * \
(cell_area.width - calc_width - \
self.get_property('xpad'))
y_offset = self.get_property('yalign') * \
(cell_area.height - calc_height - \
self.get_property('ypad'))
return x_offset, y_offset, calc_width, calc_height
This diff is collapsed.
This diff is collapsed.
......@@ -653,5 +653,3 @@ GnuPGInterface = GnuPG
if __name__ == '__main__':
_run_doctests()
# vim: se ts=3:
......@@ -31,129 +31,127 @@ import xmpp
import time
class PersonConstruct(xmpp.Node, object):
''' Not used for now, as we don't need authors/contributors in pubsub.com feeds.
They rarely exist there. '''
def __init__(self, node):
''' Create person construct from node. '''
xmpp.Node.__init__(self, node=node)
''' Not used for now, as we don't need authors/contributors in pubsub.com feeds.
They rarely exist there. '''
def __init__(self, node):
''' Create person construct from node. '''
xmpp.Node.__init__(self, node=node)
def get_name(self):
return self.getTagData('name')
def get_name(self):
return self.getTagData('name')
name = property(get_name, None, None,
'''Conveys a human-readable name for the person. Should not be None,
although some badly generated atom feeds don't put anything here
(this is non-standard behavior, still pubsub.com sometimes does that.)''')
name = property(get_name, None, None,
'''Conveys a human-readable name for the person. Should not be None,
although some badly generated atom feeds don't put anything here
(this is non-standard behavior, still pubsub.com sometimes does that.)''')
def get_uri(self):
return self.getTagData('uri')
def get_uri(self):
return self.getTagData('uri')
uri = property(get_uri, None, None,
'''Conveys an IRI associated with the person. Might be None when not set.''')
uri = property(get_uri, None, None,
'''Conveys an IRI associated with the person. Might be None when not set.''')
def get_email(self):
return self.getTagData('email')
def get_email(self):
return self.getTagData('email')
email = property(get_email, None, None,
'''Conveys an e-mail address associated with the person. Might be None when
not set.''')
email = property(get_email, None, None,
'''Conveys an e-mail address associated with the person. Might be None when
not set.''')
class Entry(xmpp.Node, object):
def __init__(self, node=None):
''' Create new atom entry object. '''
xmpp.Node.__init__(self, 'entry', node=node)
def __init__(self, node=None):
''' Create new atom entry object. '''
xmpp.Node.__init__(self, 'entry', node=node)
def __repr__(self):
return '<Atom:Entry object of id="%r">' % self.getAttr('id')
def __repr__(self):
return '<Atom:Entry object of id="%r">' % self.getAttr('id')
class OldEntry(xmpp.Node, object):
''' Parser for feeds from pubsub.com. They use old Atom 0.3 format with
their extensions. '''
def __init__(self, node=None):
''' Create new Atom 0.3 entry object. '''
xmpp.Node.__init__(self, 'entry', node=node)
def __repr__(self):
return '<Atom0.3:Entry object of id="%r">' % self.getAttr('id')
def get_feed_title(self):
''' Returns title of feed, where the entry was created. The result is the feed name
concatenated with source-feed title. '''
if self.parent is not None:
main_feed = self.parent.getTagData('title')
else:
main_feed = None
if self.getTag('feed') is not None:
source_feed = self.getTag('feed').getTagData('title')
else:
source_feed = None
if main_feed is not None and source_feed is not None:
return u'%s: %s' % (main_feed, source_feed)
elif main_feed is not None:
return main_feed
elif source_feed is not None:
return source_feed
else:
return u''
feed_title = property(get_feed_title, None, None,
''' Title of feed. It is built from entry''s original feed title and title of feed
which delivered this entry. ''')
def get_feed_link(self):
''' Get source link '''
try:
return self.getTag('feed').getTags('link',{'rel':'alternate'})[1].getData()
except Exception:
return None
feed_link = property(get_feed_link, None, None,
''' Link to main webpage of the feed. ''')
def get_title(self):
''' Get an entry's title. '''
return self.getTagData('title')
title = property(get_title, None, None,
''' Entry's title. ''')
def get_uri(self):
''' Get the uri the entry points to (entry's first link element with rel='alternate'
or without rel attribute). '''
for element in self.getTags('link'):
if 'rel' in element.attrs and element.attrs['rel']!='alternate': continue
try:
return element.attrs['href']
except AttributeError:
pass
return None
uri = property(get_uri, None, None,
''' URI that is pointed by the entry. ''')
def get_updated(self):
''' Get the time the entry was updated last time. This should be standarized,
but pubsub.com sends it in human-readable format. We won't try to parse it.
(Atom 0.3 uses the word «modified» for that).
If there's no time given in the entry, we try with <published>
and <issued> elements. '''
for name in ('updated', 'modified', 'published', 'issued'):
date = self.getTagData(name)
if date is not None: break
if date is None:
# it is not in the standard format
return time.asctime()
return date
updated = property(get_updated, None, None,
''' Last significant modification time. ''')
feed_tagline = u''
# vim: se ts=3:
''' Parser for feeds from pubsub.com. They use old Atom 0.3 format with
their extensions. '''
def __init__(self, node=None):
''' Create new Atom 0.3 entry object. '''
xmpp.Node.__init__(self, 'entry', node=node)
def __repr__(self):
return '<Atom0.3:Entry object of id="%r">' % self.getAttr('id')
def get_feed_title(self):
''' Returns title of feed, where the entry was created. The result is the feed name
concatenated with source-feed title. '''
if self.parent is not None:
main_feed = self.parent.getTagData('title')
else:
main_feed = None
if self.getTag('feed') is not None:
source_feed = self.getTag('feed').getTagData('title')
else:
source_feed = None
if main_feed is not None and source_feed is not None:
return u'%s: %s' % (main_feed, source_feed)
elif main_feed is not None:
return main_feed
elif source_feed is not None:
return source_feed
else:
return u''
feed_title = property(get_feed_title, None, None,
''' Title of feed. It is built from entry''s original feed title and title of feed
which delivered this entry. ''')
def get_feed_link(self):
''' Get source link '''
try:
return self.getTag('feed').getTags('link', {'rel':'alternate'})[1].getData()
except Exception:
return None
feed_link = property(get_feed_link, None, None,
''' Link to main webpage of the feed. ''')
def get_title(self):
''' Get an entry's title. '''
return self.getTagData('title')
title = property(get_title, None, None,
''' Entry's title. ''')
def get_uri(self):
''' Get the uri the entry points to (entry's first link element with rel='alternate'
or without rel attribute). '''
for element in self.getTags('link'):
if 'rel' in element.attrs and element.attrs['rel']!='alternate': continue
try:
return element.attrs['href']
except AttributeError:
pass
return None
uri = property(get_uri, None, None,
''' URI that is pointed by the entry. ''')
def get_updated(self):
''' Get the time the entry was updated last time. This should be standarized,
but pubsub.com sends it in human-readable format. We won't try to parse it.
(Atom 0.3 uses the word «modified» for that).
If there's no time given in the entry, we try with <published>
and <issued> elements. '''
for name in ('updated', 'modified', 'published', 'issued'):
date = self.getTagData(name)
if date is not None: break
if date is None:
# it is not in the standard format
return time.asctime()
return date
updated = property(get_updated, None, None,
''' Last significant modification time. ''')
feed_tagline = u''
This diff is collapsed.
......@@ -33,124 +33,122 @@ import logger
# DO NOT MOVE ABOVE OF import gajim
try:
import sqlite3 as sqlite # python 2.5
import sqlite3 as sqlite # python 2.5
except ImportError:
try:
from pysqlite2 import dbapi2 as sqlite
except ImportError:
raise exceptions.PysqliteNotAvailable
try:
from pysqlite2 import dbapi2 as sqlite
except ImportError:
raise exceptions.PysqliteNotAvailable
def create_log_db():
print _('creating logs database')
con = sqlite.connect(logger.LOG_DB_PATH)
os.chmod(logger.LOG_DB_PATH, 0600) # rw only for us
cur = con.cursor()
# create the tables
# kind can be
# status, gcstatus, gc_msg, (we only recv for those 3),
# single_msg_recv, chat_msg_recv, chat_msg_sent, single_msg_sent
# to meet all our needs
# logs.jid_id --> jids.jid_id but Sqlite doesn't do FK etc so it's done in python code
# jids.jid text column will be JID if TC-related, room_jid if GC-related,
# ROOM_JID/nick if pm-related.
# also check optparser.py, which updates databases on gajim updates
cur.executescript(
'''
CREATE TABLE jids(
jid_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid TEXT UNIQUE,
type INTEGER
);
CREATE TABLE unread_messages(
message_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid_id INTEGER
);