diff --git a/data/glade/preferences_window.glade b/data/glade/preferences_window.glade index d3ea20d10..c9d6a34b1 100644 --- a/data/glade/preferences_window.glade +++ b/data/glade/preferences_window.glade @@ -1962,7 +1962,6 @@ $T will be replaced by auto-not-available timeout 1 2 - @@ -1975,7 +1974,6 @@ $T will be replaced by auto-not-available timeout 2 1 2 - @@ -2066,7 +2064,6 @@ $T will be replaced by auto-not-available timeout 1 2 - @@ -2079,7 +2076,6 @@ $T will be replaced by auto-not-available timeout 2 1 2 - @@ -2102,6 +2098,74 @@ $T will be replaced by auto-not-available timeout 1 + + + True + 0 + none + + + True + 12 + + + True + 3 + 6 + 6 + + + True + 0 + STUN server: + + + GTK_FILL + + + + + True + <i>(example: stunserver.org)</i> + True + + + 2 + 3 + GTK_FILL + + + + + True + True + + + + 1 + 2 + + + + + + + + + True + <b>Connection</b> + True + + + label_item + + + + + False + 2 + + 5 diff --git a/data/pixmaps/Makefile.am b/data/pixmaps/Makefile.am index ae122a971..a7eadc116 100644 --- a/data/pixmaps/Makefile.am +++ b/data/pixmaps/Makefile.am @@ -1,15 +1,5 @@ pixmapsdir = $(pkgdatadir)/data/pixmaps nobase_dist_pixmaps_DATA = \ - $(srcdir)/events/*.png \ - $(srcdir)/agents/*.png \ - $(srcdir)/*.png \ - $(srcdir)/gajim.svg \ $(srcdir)/gajim.ico -gajimpixmapdir = $(datadir)/pixmaps -gajimpixmap_DATA = \ - $(srcdir)/gajim.png \ - $(srcdir)/gajim.svg \ - $(srcdir)/gajim_about.png - MAINTAINERCLEANFILES = Makefile.in diff --git a/data/pixmaps/gajim.icns b/data/pixmaps/gajim.icns deleted file mode 100644 index 37516d5e8..000000000 Binary files a/data/pixmaps/gajim.icns and /dev/null differ diff --git a/data/pixmaps/person.png b/data/pixmaps/person.png deleted file mode 100644 index f2169a8a2..000000000 Binary files a/data/pixmaps/person.png and /dev/null differ diff --git a/icons/Makefile.am b/icons/Makefile.am index fb75f0ef3..e61275c37 100644 --- a/icons/Makefile.am +++ b/icons/Makefile.am @@ -1,4 +1,7 @@ iconsdir = $(pkgdatadir)/icons nobase_dist_icons_DATA = $(srcdir)/*/*/*/* +systemiconsdir = $(datadir)/icons +nobase_dist_systemicons_DATA = $(srcdir)/*/*/*/gajim.* + MAINTAINERCLEANFILES = Makefile.in diff --git a/data/pixmaps/gajim_about.png b/icons/hicolor/128x128/apps/gajim_about.png similarity index 100% rename from data/pixmaps/gajim_about.png rename to icons/hicolor/128x128/apps/gajim_about.png diff --git a/data/pixmaps/cam_active.png b/icons/hicolor/16x16/actions/gajim-cam_active.png similarity index 100% rename from data/pixmaps/cam_active.png rename to icons/hicolor/16x16/actions/gajim-cam_active.png diff --git a/data/pixmaps/cam_inactive.png b/icons/hicolor/16x16/actions/gajim-cam_inactive.png similarity index 100% rename from data/pixmaps/cam_inactive.png rename to icons/hicolor/16x16/actions/gajim-cam_inactive.png diff --git a/data/pixmaps/kbd_input.png b/icons/hicolor/16x16/actions/gajim-kbd_input.png similarity index 100% rename from data/pixmaps/kbd_input.png rename to icons/hicolor/16x16/actions/gajim-kbd_input.png diff --git a/data/pixmaps/mic_active.png b/icons/hicolor/16x16/actions/gajim-mic_active.png similarity index 100% rename from data/pixmaps/mic_active.png rename to icons/hicolor/16x16/actions/gajim-mic_active.png diff --git a/data/pixmaps/mic_inactive.png b/icons/hicolor/16x16/actions/gajim-mic_inactive.png similarity index 100% rename from data/pixmaps/mic_inactive.png rename to icons/hicolor/16x16/actions/gajim-mic_inactive.png diff --git a/data/pixmaps/muc_separator.png b/icons/hicolor/16x16/actions/gajim-muc_separator.png similarity index 100% rename from data/pixmaps/muc_separator.png rename to icons/hicolor/16x16/actions/gajim-muc_separator.png diff --git a/data/pixmaps/receipt_missing.png b/icons/hicolor/16x16/actions/gajim-receipt_missing.png similarity index 100% rename from data/pixmaps/receipt_missing.png rename to icons/hicolor/16x16/actions/gajim-receipt_missing.png diff --git a/data/pixmaps/security-high.png b/icons/hicolor/16x16/actions/gajim-security_high.png similarity index 100% rename from data/pixmaps/security-high.png rename to icons/hicolor/16x16/actions/gajim-security_high.png diff --git a/data/pixmaps/security-low.png b/icons/hicolor/16x16/actions/gajim-security_low.png similarity index 100% rename from data/pixmaps/security-low.png rename to icons/hicolor/16x16/actions/gajim-security_low.png diff --git a/data/pixmaps/agents/aim.png b/icons/hicolor/32x32/categories/gajim-agent-aim.png similarity index 100% rename from data/pixmaps/agents/aim.png rename to icons/hicolor/32x32/categories/gajim-agent-aim.png diff --git a/data/pixmaps/agents/bytestreams.png b/icons/hicolor/32x32/categories/gajim-agent-bytestreams.png similarity index 100% rename from data/pixmaps/agents/bytestreams.png rename to icons/hicolor/32x32/categories/gajim-agent-bytestreams.png diff --git a/data/pixmaps/agents/conference.png b/icons/hicolor/32x32/categories/gajim-agent-conference.png similarity index 100% rename from data/pixmaps/agents/conference.png rename to icons/hicolor/32x32/categories/gajim-agent-conference.png diff --git a/data/pixmaps/agents/disc.png b/icons/hicolor/32x32/categories/gajim-agent-disc.png similarity index 100% rename from data/pixmaps/agents/disc.png rename to icons/hicolor/32x32/categories/gajim-agent-disc.png diff --git a/data/pixmaps/agents/error.png b/icons/hicolor/32x32/categories/gajim-agent-error.png similarity index 100% rename from data/pixmaps/agents/error.png rename to icons/hicolor/32x32/categories/gajim-agent-error.png diff --git a/data/pixmaps/agents/facebook.png b/icons/hicolor/32x32/categories/gajim-agent-facebook.png similarity index 100% rename from data/pixmaps/agents/facebook.png rename to icons/hicolor/32x32/categories/gajim-agent-facebook.png diff --git a/data/pixmaps/agents/gadu-gadu.png b/icons/hicolor/32x32/categories/gajim-agent-gadu-gadu.png similarity index 100% rename from data/pixmaps/agents/gadu-gadu.png rename to icons/hicolor/32x32/categories/gajim-agent-gadu-gadu.png diff --git a/data/pixmaps/agents/http-ws.png b/icons/hicolor/32x32/categories/gajim-agent-http-ws.png similarity index 100% rename from data/pixmaps/agents/http-ws.png rename to icons/hicolor/32x32/categories/gajim-agent-http-ws.png diff --git a/data/pixmaps/agents/icq.png b/icons/hicolor/32x32/categories/gajim-agent-icq.png similarity index 100% rename from data/pixmaps/agents/icq.png rename to icons/hicolor/32x32/categories/gajim-agent-icq.png diff --git a/data/pixmaps/agents/irc.png b/icons/hicolor/32x32/categories/gajim-agent-irc.png similarity index 100% rename from data/pixmaps/agents/irc.png rename to icons/hicolor/32x32/categories/gajim-agent-irc.png diff --git a/data/pixmaps/agents/jabber.png b/icons/hicolor/32x32/categories/gajim-agent-jabber.png similarity index 100% rename from data/pixmaps/agents/jabber.png rename to icons/hicolor/32x32/categories/gajim-agent-jabber.png diff --git a/data/pixmaps/agents/jud.png b/icons/hicolor/32x32/categories/gajim-agent-jud.png similarity index 100% rename from data/pixmaps/agents/jud.png rename to icons/hicolor/32x32/categories/gajim-agent-jud.png diff --git a/data/pixmaps/agents/mail.png b/icons/hicolor/32x32/categories/gajim-agent-mail.png similarity index 100% rename from data/pixmaps/agents/mail.png rename to icons/hicolor/32x32/categories/gajim-agent-mail.png diff --git a/data/pixmaps/agents/mrim.png b/icons/hicolor/32x32/categories/gajim-agent-mrim.png similarity index 100% rename from data/pixmaps/agents/mrim.png rename to icons/hicolor/32x32/categories/gajim-agent-mrim.png diff --git a/data/pixmaps/agents/msn.png b/icons/hicolor/32x32/categories/gajim-agent-msn.png similarity index 100% rename from data/pixmaps/agents/msn.png rename to icons/hicolor/32x32/categories/gajim-agent-msn.png diff --git a/data/pixmaps/agents/pubsub.png b/icons/hicolor/32x32/categories/gajim-agent-pubsub.png similarity index 100% rename from data/pixmaps/agents/pubsub.png rename to icons/hicolor/32x32/categories/gajim-agent-pubsub.png diff --git a/data/pixmaps/agents/rss.png b/icons/hicolor/32x32/categories/gajim-agent-rss.png similarity index 100% rename from data/pixmaps/agents/rss.png rename to icons/hicolor/32x32/categories/gajim-agent-rss.png diff --git a/data/pixmaps/agents/sip.png b/icons/hicolor/32x32/categories/gajim-agent-sip.png similarity index 100% rename from data/pixmaps/agents/sip.png rename to icons/hicolor/32x32/categories/gajim-agent-sip.png diff --git a/data/pixmaps/agents/sms.png b/icons/hicolor/32x32/categories/gajim-agent-sms.png similarity index 100% rename from data/pixmaps/agents/sms.png rename to icons/hicolor/32x32/categories/gajim-agent-sms.png diff --git a/data/pixmaps/agents/tv.png b/icons/hicolor/32x32/categories/gajim-agent-tv.png similarity index 100% rename from data/pixmaps/agents/tv.png rename to icons/hicolor/32x32/categories/gajim-agent-tv.png diff --git a/data/pixmaps/agents/weather.png b/icons/hicolor/32x32/categories/gajim-agent-weather.png similarity index 100% rename from data/pixmaps/agents/weather.png rename to icons/hicolor/32x32/categories/gajim-agent-weather.png diff --git a/data/pixmaps/agents/yahoo.png b/icons/hicolor/32x32/categories/gajim-agent-yahoo.png similarity index 100% rename from data/pixmaps/agents/yahoo.png rename to icons/hicolor/32x32/categories/gajim-agent-yahoo.png diff --git a/data/pixmaps/events/chat_msg_recv.png b/icons/hicolor/48x48/actions/gajim-chat_msg_recv.png similarity index 100% rename from data/pixmaps/events/chat_msg_recv.png rename to icons/hicolor/48x48/actions/gajim-chat_msg_recv.png diff --git a/data/pixmaps/events/connection_lost.png b/icons/hicolor/48x48/actions/gajim-connection_lost.png similarity index 100% rename from data/pixmaps/events/connection_lost.png rename to icons/hicolor/48x48/actions/gajim-connection_lost.png diff --git a/data/pixmaps/events/ft_done.png b/icons/hicolor/48x48/actions/gajim-ft_done.png similarity index 100% rename from data/pixmaps/events/ft_done.png rename to icons/hicolor/48x48/actions/gajim-ft_done.png diff --git a/data/pixmaps/events/ft_error.png b/icons/hicolor/48x48/actions/gajim-ft_error.png similarity index 100% rename from data/pixmaps/events/ft_error.png rename to icons/hicolor/48x48/actions/gajim-ft_error.png diff --git a/data/pixmaps/events/ft_request.png b/icons/hicolor/48x48/actions/gajim-ft_request.png similarity index 100% rename from data/pixmaps/events/ft_request.png rename to icons/hicolor/48x48/actions/gajim-ft_request.png diff --git a/data/pixmaps/events/ft_stopped.png b/icons/hicolor/48x48/actions/gajim-ft_stopped.png similarity index 100% rename from data/pixmaps/events/ft_stopped.png rename to icons/hicolor/48x48/actions/gajim-ft_stopped.png diff --git a/data/pixmaps/events/gc_invitation.png b/icons/hicolor/48x48/actions/gajim-gc_invitation.png similarity index 100% rename from data/pixmaps/events/gc_invitation.png rename to icons/hicolor/48x48/actions/gajim-gc_invitation.png diff --git a/data/pixmaps/events/new_email_recv.png b/icons/hicolor/48x48/actions/gajim-new_email_recv.png similarity index 100% rename from data/pixmaps/events/new_email_recv.png rename to icons/hicolor/48x48/actions/gajim-new_email_recv.png diff --git a/data/pixmaps/events/priv_msg_recv.png b/icons/hicolor/48x48/actions/gajim-priv_msg_recv.png similarity index 100% rename from data/pixmaps/events/priv_msg_recv.png rename to icons/hicolor/48x48/actions/gajim-priv_msg_recv.png diff --git a/data/pixmaps/security-high-big.png b/icons/hicolor/48x48/actions/gajim-security_high.png similarity index 100% rename from data/pixmaps/security-high-big.png rename to icons/hicolor/48x48/actions/gajim-security_high.png diff --git a/data/pixmaps/security-low-big.png b/icons/hicolor/48x48/actions/gajim-security_low.png similarity index 100% rename from data/pixmaps/security-low-big.png rename to icons/hicolor/48x48/actions/gajim-security_low.png diff --git a/data/pixmaps/events/single_msg_recv.png b/icons/hicolor/48x48/actions/gajim-single_msg_recv.png similarity index 100% rename from data/pixmaps/events/single_msg_recv.png rename to icons/hicolor/48x48/actions/gajim-single_msg_recv.png diff --git a/data/pixmaps/events/subscription_request.png b/icons/hicolor/48x48/actions/gajim-subscription_request.png similarity index 100% rename from data/pixmaps/events/subscription_request.png rename to icons/hicolor/48x48/actions/gajim-subscription_request.png diff --git a/data/pixmaps/events/unsubscribed.png b/icons/hicolor/48x48/actions/gajim-unsubscribed.png similarity index 100% rename from data/pixmaps/events/unsubscribed.png rename to icons/hicolor/48x48/actions/gajim-unsubscribed.png diff --git a/data/pixmaps/gajim.png b/icons/hicolor/64x64/apps/gajim.png similarity index 100% rename from data/pixmaps/gajim.png rename to icons/hicolor/64x64/apps/gajim.png diff --git a/data/pixmaps/gajim.svg b/icons/hicolor/scalable/apps/gajim.svg similarity index 100% rename from data/pixmaps/gajim.svg rename to icons/hicolor/scalable/apps/gajim.svg diff --git a/src/chat_control.py b/src/chat_control.py index 7b52d8b34..9bf83be5d 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1274,21 +1274,15 @@ class ChatControl(ChatControlBase): id_ = self._audio_button.connect('toggled', self.on_audio_button_toggled) self.handlers[id_] = self._audio_button # add a special img - path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'mic_inactive.png') - img = gtk.Image() - img.set_from_file(path_to_img) - self._audio_button.set_image(img) + gtkgui_helpers.add_image_to_button(self._audio_button, + 'gajim-mic_inactive') self._video_button = self.xml.get_widget('video_togglebutton') id_ = self._video_button.connect('toggled', self.on_video_button_toggled) self.handlers[id_] = self._video_button # add a special img - path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'cam_inactive.png') - img = gtk.Image() - img.set_from_file(path_to_img) - self._video_button.set_image(img) + gtkgui_helpers.add_image_to_button(self._video_button, + 'gajim-cam_inactive') self._send_file_button = self.xml.get_widget('send_file_button') # add a special img for send file button @@ -1796,12 +1790,13 @@ class ChatControl(ChatControlBase): banner_name_label.set_tooltip_text(label_tooltip) def on_jingle_button_toggled(self, widget, jingle_type): - path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps', '%s_%s.png' - % ({'audio': 'mic', 'video': 'cam'}[jingle_type], - {True: 'active', False: 'inactive'}[widget.get_active()])) + img_name = '%s_%s' % ({'audio': 'mic', 'video': 'cam'}[jingle_type], + {True: 'active', False: 'inactive'}[widget.get_active()]) + path_to_img = gtkgui_helpers.get_icon_path(img_name) if widget.get_active(): - if getattr(self, jingle_type + '_state') == self.JINGLE_STATE_AVAILABLE: + if getattr(self, jingle_type + '_state') == \ + self.JINGLE_STATE_AVAILABLE: sid = getattr(gajim.connections[self.account], 'start_' + jingle_type)(self.contact.get_full_jid()) getattr(self, 'set_' + jingle_type + '_state')('connecting', sid) @@ -1886,11 +1881,12 @@ class ChatControl(ChatControlBase): if authenticated: #About encrypted chat session authenticated_string = _('and authenticated') - self.lock_image.set_from_file(os.path.join(gajim.DATA_DIR, 'pixmaps', 'security-high.png')) + img_path = gtkgui_helpers.get_icon_path('gajim-security_high') else: #About encrypted chat session authenticated_string = _('and NOT authenticated') - self.lock_image.set_from_file(os.path.join(gajim.DATA_DIR, 'pixmaps', 'security-low.png')) + img_path = gtkgui_helpers.get_icon_path('gajim-security_low') + self.lock_image.set_from_file(img_path) #status will become 'is' or 'is not', authentificaed will become #'and authentificated' or 'and not authentificated', logged will become diff --git a/src/command_system/errors.py b/src/command_system/errors.py index 877a22acb..f687b72e3 100644 --- a/src/command_system/errors.py +++ b/src/command_system/errors.py @@ -20,13 +20,15 @@ class BaseError(Exception): """ def __init__(self, message, command=None, name=None): + self.message = message + self.command = command self.name = name if command and not name: self.name = command.first_name - super(BaseError, self).__init__(message) + super(BaseError, self).__init__() class DefinitionError(BaseError): """ diff --git a/src/common/check_paths.py b/src/common/check_paths.py index c4864fc78..122ab5528 100644 --- a/src/common/check_paths.py +++ b/src/common/check_paths.py @@ -27,18 +27,11 @@ import os import sys import stat -import exceptions from common import gajim import logger # DO NOT MOVE ABOVE OF import gajim -try: - import sqlite3 as sqlite # python 2.5 -except ImportError: - try: - from pysqlite2 import dbapi2 as sqlite - except ImportError: - raise exceptions.PysqliteNotAvailable +import sqlite3 as sqlite def create_log_db(): print _('creating logs database') diff --git a/src/common/config.py b/src/common/config.py index 5108e60b1..fb5f0ebfd 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -276,6 +276,7 @@ class Config: 'audio_output_device': [opt_str, 'autoaudiosink'], 'video_input_device': [opt_str, 'autovideosrc ! videoscale ! ffmpegcolorspace'], 'video_output_device': [opt_str, 'autovideosink'], + 'stun_server': [opt_str, '', _('STUN server to use when using jingle')], } __options_per_key = { diff --git a/src/common/contacts.py b/src/common/contacts.py index 25ffb8237..8f8397047 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -31,7 +31,7 @@ from common import caps from common.account import Account -import common.gajim +import common.gajim class XMPPEntity(object): """ @@ -175,9 +175,7 @@ class Contact(CommonContact): def is_transport(self): # if not '@' or '@' starts the jid then contact is transport - if self.jid.find('@') <= 0: - return True - return False + return self.jid.find('@') <= 0 class GC_Contact(CommonContact): @@ -443,18 +441,14 @@ class Contacts_New(): """ Remove all contacts for a given jid """ - if jid not in self._contacts: - return - del self._contacts[jid] + if jid in self._contacts: + del self._contacts[jid] def get_contacts(self, jid): """ Return the list of contact instances for this jid """ - if jid in self._contacts: - return self._contacts[jid] - else: - return [] + return self._contacts.get(jid, []) def get_contact(self, jid, resource=None): ### WARNING ### @@ -472,7 +466,6 @@ class Contacts_New(): for c in self._contacts[jid]: if c.resource == resource: return c - return None def iter_contacts(self): for jid in self._contacts.keys(): @@ -492,7 +485,6 @@ class Contacts_New(): def get_first_contact_from_jid(self, jid): if jid in self._contacts: return self._contacts[jid][0] - return None def get_contacts_from_group(self, group): """ @@ -538,9 +530,8 @@ class GC_Contacts(): del self._rooms[gc_contact.room_jid] def remove_room(self, room_jid): - if room_jid not in self._rooms: - return - del self._rooms[room_jid] + if room_jid in self._rooms: + del self._rooms[room_jid] def get_gc_list(self): return self._rooms.keys() @@ -643,7 +634,7 @@ class MetacontactManager(): def remove_metacontact(self, account, jid): if not account in self._metacontacts_tags: - return None + return found = None for tag in self._metacontacts_tags[account]: diff --git a/src/common/dbus_support.py b/src/common/dbus_support.py index 24d4525ac..4762b474d 100644 --- a/src/common/dbus_support.py +++ b/src/common/dbus_support.py @@ -63,7 +63,7 @@ class SystemBus: raise exceptions.DbusNotSupported if not self.present(): - raise exceptions.SystemBusNotPresent + raise exceptions.SystemBusNotPresent return self.system_bus def bus(self): diff --git a/src/common/exceptions.py b/src/common/exceptions.py index 75f5b8913..090255768 100644 --- a/src/common/exceptions.py +++ b/src/common/exceptions.py @@ -21,17 +21,6 @@ ## along with Gajim. If not, see . ## -class PysqliteNotAvailable(Exception): - """ - Sqlite2 is not installed or python bindings are missing - """ - - def __init__(self): - Exception.__init__(self) - - def __str__(self): - return _('pysqlite2 (aka python-pysqlite2) dependency is missing. Exiting...') - class PysqliteOperationalError(Exception): """ Sqlite2 raised pysqlite2.dbapi2.OperationalError @@ -86,7 +75,20 @@ class SessionBusNotPresent(Exception): Exception.__init__(self) def __str__(self): - return _('Session bus is not available.\nTry reading http://trac.gajim.org/wiki/GajimDBus') + return _('Session bus is not available.\nTry reading %(url)s') % \ + {'url': 'http://trac.gajim.org/wiki/GajimDBus'} + +class SystemBusNotPresent(Exception): + """ + This exception indicates that there is no session daemon + """ + + def __init__(self): + Exception.__init__(self) + + def __str__(self): + return _('System bus is not available.\nTry reading %(url)s') % \ + {'url': 'http://trac.gajim.org/wiki/GajimDBus'} class NegotiationError(Exception): """ diff --git a/src/common/jingle.py b/src/common/jingle.py index 65803a2ed..f4c002ca6 100644 --- a/src/common/jingle.py +++ b/src/common/jingle.py @@ -25,7 +25,6 @@ Handles the jingle signalling protocol # - video integration # * config: # - codecs -# - STUN # * figure out why it doesn't work with pidgin: # That's maybe a bug in pidgin: diff --git a/src/common/jingle_content.py b/src/common/jingle_content.py index 703f1a054..0dd013660 100644 --- a/src/common/jingle_content.py +++ b/src/common/jingle_content.py @@ -23,6 +23,12 @@ def get_jingle_content(node): return contents[namespace](node) +class FailedApplication(Exception): + """ + Exception that should be raised when a content fails to setup. + """ + + class JingleContent(object): """ An abstraction of content in Jingle sessions @@ -106,6 +112,9 @@ class JingleContent(object): payload=payload) def send_candidate(self, candidate): + """ + Send a transport candidate for a previously defined transport. + """ content = self.__content() content.addChild(self.transport.make_transport([candidate])) self.session.send_transport_info(content) diff --git a/src/common/jingle_rtp.py b/src/common/jingle_rtp.py index e64c175c0..2795e32ad 100644 --- a/src/common/jingle_rtp.py +++ b/src/common/jingle_rtp.py @@ -19,11 +19,12 @@ import gobject import xmpp import farsight, gst +from glib import GError import gajim from jingle_transport import JingleTransportICEUDP -from jingle_content import contents, JingleContent +from jingle_content import contents, JingleContent, FailedApplication class JingleRTPContent(JingleContent): @@ -35,12 +36,12 @@ class JingleRTPContent(JingleContent): self._dtmf_running = False self.farsight_media = {'audio': farsight.MEDIA_TYPE_AUDIO, 'video': farsight.MEDIA_TYPE_VIDEO}[media] - self.got_codecs = False self.candidates_ready = False # True when local candidates are prepared self.callbacks['session-initiate'] += [self.__on_remote_codecs] self.callbacks['content-add'] += [self.__on_remote_codecs] + self.callbacks['description-info'] += [self.__on_remote_codecs] self.callbacks['content-accept'] += [self.__on_remote_codecs, self.__on_content_accept] self.callbacks['session-accept'] += [self.__on_remote_codecs, @@ -59,7 +60,7 @@ class JingleRTPContent(JingleContent): # conference self.conference = gst.element_factory_make('fsrtpconference') - self.conference.set_property("sdes-cname", self.session.ourjid) + self.conference.set_property('sdes-cname', self.session.ourjid) self.pipeline.add(self.conference) self.funnel = None @@ -69,8 +70,16 @@ class JingleRTPContent(JingleContent): # FIXME: Consider a workaround, here... # pidgin and telepathy-gabble don't follow the XEP, and it won't work # due to bad controlling-mode - params = {'controlling-mode': self.session.weinitiate,# 'debug': False} - 'stun-ip': '69.0.208.27', 'debug': False} + params = {'controlling-mode': self.session.weinitiate, 'debug': False} + stun_server = gajim.config.get('stun-server') + if stun_server: + try: + ip = socket.getaddrinfo(stun_server, 0, socket.AF_UNSPEC, + socket.SOCK_STREAM)[0][4][0] + except socket.gaierror, (errnum, errstr): + log.warn('Lookup of stun ip failed: %s' % errstr) + else: + params['stun-ip'] = ip self.p2pstream = self.p2psession.new_stream(participant, farsight.DIRECTION_RECV, 'nice', params) @@ -79,6 +88,18 @@ class JingleRTPContent(JingleContent): return (JingleContent.is_ready(self) and self.candidates_ready and self.p2psession.get_property('codecs-ready')) + def make_bin_from_config(self, config_key, pipeline, text): + try: + bin = gst.parse_bin_from_description(pipeline + % gajim.config.get(config_key), True) + return bin + except GError, error_str: + self.session.connection.dispatch('ERROR', + (_("%s configuration error") % text.capitalize(), + _("Couldn't setup %s. Check your configuration.\n\nError was:\n%s") + % (text, error_str))) + raise FailedApplication + def add_remote_candidates(self, candidates): JingleContent.add_remote_candidates(self, candidates) # FIXME: connectivity should not be etablished yet @@ -87,6 +108,9 @@ class JingleRTPContent(JingleContent): self.p2pstream.set_remote_candidates(candidates) def batch_dtmf(self, events): + """ + Send several DTMF tones + """ if self._dtmf_running: raise Exception # TODO: Proper exception self._dtmf_running = True @@ -177,8 +201,6 @@ class JingleRTPContent(JingleContent): """ Get peer codecs from what we get from peer """ - if self.got_codecs: - return codecs = [] for codec in content.getTag('description').iterTags('payload-type'): @@ -197,7 +219,6 @@ class JingleRTPContent(JingleContent): # glib.GError: There was no intersection between the remote codecs and # the local ones self.p2pstream.set_remote_codecs(codecs) - self.got_codecs = True def iter_codecs(self): codecs = self.p2psession.get_property('codecs') @@ -252,17 +273,12 @@ class JingleAudio(JingleRTPContent): self.p2psession.set_codec_preferences(codecs) # the local parts - try: - self.sink = gst.parse_bin_from_description(gajim.config.get('audio_output_device'), True) - except: - self.session.connection.dispatch('ERROR', (_("Audio configuration error"), - _("Couldn't setup audio output. Check your audio configuration."))) + # TODO: Add queues? + src_bin = self.make_bin_from_config('audio_input_device', + '%s ! audioconvert', _("audio input")) - try: - src_bin = gst.parse_bin_from_description(gajim.config.get('audio_input_device'), True) - except: - self.session.connection.dispatch('ERROR', (_("Audio configuration error"), - _("Couldn't setup audio input. Check your audio configuration."))) + self.sink = self.make_bin_from_config('audio_output_device', + 'audioconvert ! %s', _("audio output")) self.mic_volume = src_bin.get_by_name('gajim_vol') self.mic_volume.set_property('volume', 1) @@ -290,25 +306,19 @@ class JingleVideo(JingleRTPContent): JingleRTPContent.setup_stream(self) # the local parts - try: - src_bin = gst.parse_bin_from_description(gajim.config.get('video_input_device'), True) - except: - self.session.connection.dispatch('ERROR', (_("Video configuration error"), - _("Couldn't setup video input. Check your video configuration."))) - caps = gst.element_factory_make('capsfilter') - caps.set_property('caps', gst.caps_from_string('video/x-raw-yuv, width=320, height=240')) + src_bin = self.make_bin_from_config('video_input_device', + '%s ! videoscale ! ffmpegcolorspace', _("video input")) + #caps = gst.element_factory_make('capsfilter') + #caps.set_property('caps', gst.caps_from_string('video/x-raw-yuv, width=320, height=240')) - self.pipeline.add(src_bin, caps) - src_bin.link(caps) + self.pipeline.add(src_bin)#, caps) + #src_bin.link(caps) - try: - self.sink = gst.parse_bin_from_description(gajim.config.get('video_output_device'), True) - except: - self.session.connection.dispatch('ERROR', (_("Video configuration error"), - _("Couldn't setup video output. Check your video configuration."))) + self.sink = self.make_bin_from_config('video_output_device', + '%s ! videoscale ! ffmpegcolorspace', _("video output")) self.pipeline.add(self.sink) - caps.get_pad('src').link(self.p2psession.get_property('sink-pad')) + src_bin.get_pad('src').link(self.p2psession.get_property('sink-pad')) self.p2pstream.connect('src-pad-added', self._on_src_pad_added) # The following is needed for farsight to process ICE requests: diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index 5fcc19029..806207157 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -16,12 +16,11 @@ Handles Jingle sessions (XEP 0166) """ #TODO: -# * Have JingleContent here # * 'senders' attribute of 'content' element # * security preconditions # * actions: # - content-modify -# - description-info, session-info +# - session-info # - security-info # - transport-accept, transport-reject # - Tie-breaking @@ -30,7 +29,7 @@ Handles Jingle sessions (XEP 0166) import gajim #Get rid of that? import xmpp from jingle_transport import get_jingle_transport -from jingle_content import get_jingle_content +from jingle_content import get_jingle_content, FailedApplication # FIXME: Move it to JingleSession.States? class JingleStates(object): @@ -55,7 +54,8 @@ class TieBreak(Exception): class JingleSession(object): """ - This represents one jingle session + This represents one jingle session, that is, one or more content types + negotiated between an initiator and a responder. """ def __init__(self, con, weinitiate, jid, sid=None): @@ -394,8 +394,8 @@ class JingleSession(object): raise OutOfOrder parse_result = self.__parse_contents(jingle) - contents = parse_result[2] - rejected_contents = parse_result[3] + contents = parse_result[0] + rejected_contents = parse_result[1] for name, creator in rejected_contents: # TODO @@ -426,21 +426,13 @@ class JingleSession(object): # error. # Lets check what kind of jingle session does the peer want - contents_ok, transports_ok, contents, pouet = self.__parse_contents(jingle) + contents, contents_rejected, reason = self.__parse_contents(jingle) # If there's no content we understand... - if not contents_ok: + if not contents: # TODO: http://xmpp.org/extensions/xep-0166.html#session-terminate reason = xmpp.Node('reason') - reason.setTag('unsupported-applications') - self.__ack(stanza, jingle, error, action) - self._session_terminate(reason) - raise xmpp.NodeProcessed - - if not transports_ok: - # TODO: http://xmpp.org/extensions/xep-0166.html#session-terminate - reason = xmpp.Node('reason') - reason.setTag('unsupported-transports') + reason.setTag(reason) self.__ack(stanza, jingle, error, action) self._session_terminate(reason) raise xmpp.NodeProcessed @@ -485,26 +477,37 @@ class JingleSession(object): # TODO: Needs some reworking contents = [] contents_rejected = [] - contents_ok = False - transports_ok = False + reasons = set() for element in jingle.iterTags('content'): transport = get_jingle_transport(element.getTag('transport')) content_type = get_jingle_content(element.getTag('description')) if content_type: - contents_ok = True - if transport: - content = content_type(self, transport) - self.add_content(element['name'], - content, 'peer') - contents.append((content.media,)) - transports_ok = True - else: - contents_rejected.append((element['name'], 'peer')) + try: + if transport: + content = content_type(self, transport) + self.add_content(element['name'], + content, 'peer') + contents.append((content.media,)) + else: + reasons.add('unsupported-transports') + contents_rejected.append((element['name'], 'peer')) + except FailedApplication: + reasons.add('failed-application') else: contents_rejected.append((element['name'], 'peer')) + failed.add('unsupported-applications') - return (contents_ok, transports_ok, contents, contents_rejected) + failure_reason = None + + # Store the first reason of failure + for reason in ('failed-application', 'unsupported-transports', + 'unsupported-applications'): + if reason in reasons: + failure_reason = reason + break + + return (contents, contents_rejected, failure_reason) def __dispatch_error(self, error, jingle_error=None, text=None): if jingle_error: diff --git a/src/common/logger.py b/src/common/logger.py index c484246db..507b29cfa 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -38,13 +38,7 @@ from cStringIO import StringIO import exceptions import gajim -try: - import sqlite3 as sqlite # python 2.5 -except ImportError: - try: - from pysqlite2 import dbapi2 as sqlite - except ImportError: - raise exceptions.PysqliteNotAvailable +import sqlite3 as sqlite import configpaths LOG_DB_PATH = configpaths.gajimpaths['LOG_DB'] diff --git a/src/common/multimedia_helpers.py b/src/common/multimedia_helpers.py index 59d8b635f..4a2a4fb2e 100644 --- a/src/common/multimedia_helpers.py +++ b/src/common/multimedia_helpers.py @@ -78,11 +78,9 @@ class VideoInputManager(DeviceManager): self.detect_element('videotestsrc', _('Video test'), '%s is-live=true') # Auto src - self.detect_element('autovideosrc', _('Autodetect'), - '%s ! videoscale ! ffmpegcolorspace') + self.detect_element('autovideosrc', _('Autodetect')) # V4L2 src ; TODO: Figure out why it doesn't work - self.detect_element('v4l2src', _('V4L2: %s'), - '%s ! videoscale ! ffmpegcolorspace') + self.detect_element('v4l2src', _('V4L2: %s')) # Funny things, just to test... # self.devices['GOOM'] = 'audiotestsrc ! goom' # self.devices['screen'] = 'ximagesrc' diff --git a/src/common/optparser.py b/src/common/optparser.py index 33aaa8c9d..fa7b99daa 100644 --- a/src/common/optparser.py +++ b/src/common/optparser.py @@ -34,14 +34,7 @@ from common import gajim from common import helpers from common import caps -import exceptions -try: - import sqlite3 as sqlite # python 2.5 -except ImportError: - try: - from pysqlite2 import dbapi2 as sqlite - except ImportError: - raise exceptions.PysqliteNotAvailable +import sqlite3 as sqlite import logger class OptionsParser: diff --git a/src/config.py b/src/config.py index 2ff9ff73b..5b7a0c8ce 100644 --- a/src/config.py +++ b/src/config.py @@ -59,7 +59,12 @@ from common.zeroconf import connection_zeroconf from common import dataforms from common import GnuPG -from common.multimedia_helpers import AudioInputManager, AudioOutputManager, VideoInputManager, VideoOutputManager +try: + from common.multimedia_helpers import AudioInputManager, AudioOutputManager + from common.multimedia_helpers import VideoInputManager, VideoOutputManager + HAS_GST = True +except ImportError: + HAS_GST = False from common.exceptions import GajimGeneralException @@ -416,8 +421,7 @@ class PreferencesWindow: buf = self.xml.get_widget('msg_textview').get_buffer() buf.connect('changed', self.on_msg_textview_changed) - ### Style tab ### - # Audio + ### Audio / Video tab ### def create_av_combobox(opt_name, device_dict): combobox = self.xml.get_widget(opt_name + '_combobox') cell = gtk.CellRendererText() @@ -431,10 +435,21 @@ class PreferencesWindow: if gajim.config.get(opt_name + '_device') == value: combobox.set_active(index) - create_av_combobox('audio_input', AudioInputManager().get_devices()) - create_av_combobox('audio_output', AudioOutputManager().get_devices()) - create_av_combobox('video_input', VideoInputManager().get_devices()) - create_av_combobox('video_output', VideoOutputManager().get_devices()) + if HAS_GST: + create_av_combobox('audio_input', AudioInputManager().get_devices()) + create_av_combobox('audio_output', AudioOutputManager().get_devices()) + create_av_combobox('video_input', VideoInputManager().get_devices()) + create_av_combobox('video_output', VideoOutputManager().get_devices()) + else: + for opt_name in ('audio_input', 'audio_output', 'video_input', + 'video_output'): + combobox = self.xml.get_widget(opt_name + '_combobox') + combobox.set_sensitive(False) + + # Connection + entry = self.xml.get_widget('stun_server_entry') + entry.set_text(gajim.config.get('stun_server')) + ### Advanced tab ### # open links with if os.name == 'nt': @@ -1046,6 +1061,9 @@ class PreferencesWindow: def on_video_output_combobox_changed(self, widget): self.on_av_combobox_changed(widget, 'video_output') + def stun_server_entry_changed(self, widget): + gajim.config.set('stun_server', widget.get_text().decode('utf-8')) + def on_applications_combobox_changed(self, widget): gajim.config.set('autodetect_browser_mailer', False) if widget.get_active() == 4: @@ -1419,8 +1437,7 @@ class AccountsWindow: self.accounts_treeview = self.xml.get_widget('accounts_treeview') self.remove_button = self.xml.get_widget('remove_button') self.rename_button = self.xml.get_widget('rename_button') - path_to_kbd_input_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'kbd_input.png') + path_to_kbd_input_img = gtkgui_helpers.get_icon_path('gajim-kbd_input') img = self.xml.get_widget('rename_image') img.set_from_file(path_to_kbd_input_img) self.notebook = self.xml.get_widget('notebook') @@ -3354,7 +3371,7 @@ class AccountCreationWizardWindow: if self.modify: img.set_from_stock(gtk.STOCK_APPLY, gtk.ICON_SIZE_DIALOG) else: - path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'gajim.png') + path_to_file = gtkgui_helpers.get_icon_path('gajim', 48) img.set_from_file(path_to_file) self.show_vcard_checkbutton.set_active(not self.modify) self.notebook.set_current_page(6) # show finish page diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 292d524c2..b7ee783ab 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -169,10 +169,9 @@ class ConversationTextview(gobject.GObject): ) ) - FOCUS_OUT_LINE_PIXBUF = gtk.gdk.pixbuf_new_from_file(os.path.join( - gajim.DATA_DIR, 'pixmaps', 'muc_separator.png')) - XEP0184_WARNING_PIXBUF = gtk.gdk.pixbuf_new_from_file(os.path.join( - gajim.DATA_DIR, 'pixmaps', 'receipt_missing.png')) + FOCUS_OUT_LINE_PIXBUF = gtkgui_helpers.get_icon_pixmap('gajim-muc_separator') + XEP0184_WARNING_PIXBUF = gtkgui_helpers.get_icon_pixmap( + 'gajim-receipt_missing') # smooth scroll constants MAX_SCROLL_TIME = 0.4 # seconds diff --git a/src/dialogs.py b/src/dialogs.py index a82f3a8af..e9ed3344f 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -1190,8 +1190,7 @@ class AboutDialog: dlg.props.wrap_license = True - pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join( - gajim.DATA_DIR, 'pixmaps', 'gajim_about.png')) + pixbuf = gtkgui_helpers.get_icon_pixmap('gajim-about', 64) dlg.set_logo(pixbuf) #here you write your name in the form Name FamilyName @@ -2463,9 +2462,7 @@ class PopupNotificationWindow: # default image if not path_to_image: - path_to_image = os.path.abspath( - os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'chat_msg_recv.png')) # img to display + path_to_image = gtkgui_helpers.get_icon_path('gajim-chat_msg_recv', 48) if event_type == _('Contact Signed In'): bg_color = 'limegreen' @@ -4540,43 +4537,37 @@ class ESessionInfoWindow: def update_info(self): labeltext = _('''Your chat session with %(jid)s is encrypted.\n\nThis session's Short Authentication String is %(sas)s.''') % {'jid': self.session.jid, 'sas': self.session.sas} - dir_ = os.path.join(gajim.DATA_DIR, 'pixmaps') if self.session.verified_identity: labeltext += '\n\n' + _('''You have already verified this contact's identity.''') - security_image = 'security-high-big.png' + security_image = 'gajim-security_high' if self.session.control: self.session.control._show_lock_image(True, 'E2E', True, - self.session.is_loggable(), True) + self.session.is_loggable(), True) verification_status = _('''Contact's identity verified''') self.window.set_title(verification_status) self.xml.get_widget('verification_status_label').set_markup( - '' + - verification_status + - '') + '%s' % verification_status) self.xml.get_widget('dialog-action_area1').set_no_show_all(True) self.button_label.set_text(_('Verify again...')) else: if self.session.control: self.session.control._show_lock_image(True, 'E2E', True, - self.session.is_loggable(), False) + self.session.is_loggable(), False) labeltext += '\n\n' + _('''To be certain that only the expected person can read your messages or send you messages, you need to verify their identity by clicking the button below.''') - security_image = 'security-low-big.png' + security_image = 'gajim-security_low' verification_status = _('''Contact's identity NOT verified''') self.window.set_title(verification_status) self.xml.get_widget('verification_status_label').set_markup( - '' + - verification_status + - '') + '%s' % verification_status) self.button_label.set_text(_('Verify...')) - path = os.path.join(dir_, security_image) - filename = os.path.abspath(path) - self.security_image.set_from_file(filename) + path = gtkgui_helpers.get_icon_path(security_image, 32) + self.security_image.set_from_file(path) self.xml.get_widget('info_display').set_markup(labeltext) @@ -4622,13 +4613,13 @@ class GPGInfoWindow: verification_status = _('''Contact's identity NOT verified''') info = _('The contact\'s key (%s) does not match the key ' 'assigned in Gajim.') % keyID[:8] - image = 'security-low-big.png' + image = 'gajim-security_low' elif not keyID: # No key assigned nor a key is used by remote contact verification_status = _('No GPG key assigned') info = _('No GPG key is assigned to this contact. So you cannot ' 'encrypt messages.') - image = 'security-low-big.png' + image = 'gajim-security_low' else: error = gajim.connections[account].gpg.encrypt('test', [keyID])[1] if error: @@ -4636,21 +4627,19 @@ class GPGInfoWindow: info = _('GPG key is assigned to this contact, but you do not ' 'trust his key, so message cannot be encrypted. Use ' 'your GPG client to trust this key.') - image = 'security-low-big.png' + image = 'gajim-security_low' else: verification_status = _('''Contact's identity verified''') info = _('GPG Key is assigned to this contact, and you trust his ' 'key, so messages will be encrypted.') - image = 'security-high-big.png' + image = 'gajim-security_high' status_label.set_markup('%s' % \ verification_status) info_label.set_markup(info) - dir_ = os.path.join(gajim.DATA_DIR, 'pixmaps') - path = os.path.join(dir_, image) - filename = os.path.abspath(path) - security_image.set_from_file(filename) + path = gtkgui_helpers.get_icon_path(image, 32) + security_image.set_from_file(path) xml.signal_autoconnect(self) self.window.show_all() diff --git a/src/disco.py b/src/disco.py index da9021dd4..8e5bc1e92 100644 --- a/src/disco.py +++ b/src/disco.py @@ -73,44 +73,44 @@ def _gen_agent_type_info(): (0, 0): (None, None), # Jabber server - ('server', 'im'): (ToplevelAgentBrowser, 'jabber.png'), - ('services', 'jabber'): (ToplevelAgentBrowser, 'jabber.png'), - ('hierarchy', 'branch'): (AgentBrowser, 'jabber.png'), + ('server', 'im'): (ToplevelAgentBrowser, 'jabber'), + ('services', 'jabber'): (ToplevelAgentBrowser, 'jabber'), + ('hierarchy', 'branch'): (AgentBrowser, 'jabber'), # Services - ('conference', 'text'): (MucBrowser, 'conference.png'), - ('headline', 'rss'): (AgentBrowser, 'rss.png'), - ('headline', 'weather'): (False, 'weather.png'), - ('gateway', 'weather'): (False, 'weather.png'), - ('_jid', 'weather'): (False, 'weather.png'), - ('gateway', 'sip'): (False, 'sip.png'), - ('directory', 'user'): (None, 'jud.png'), - ('pubsub', 'generic'): (PubSubBrowser, 'pubsub.png'), - ('pubsub', 'service'): (PubSubBrowser, 'pubsub.png'), - ('proxy', 'bytestreams'): (None, 'bytestreams.png'), # Socks5 FT proxy - ('headline', 'newmail'): (ToplevelAgentBrowser, 'mail.png'), + ('conference', 'text'): (MucBrowser, 'conference'), + ('headline', 'rss'): (AgentBrowser, 'rss'), + ('headline', 'weather'): (False, 'weather'), + ('gateway', 'weather'): (False, 'weather'), + ('_jid', 'weather'): (False, 'weather'), + ('gateway', 'sip'): (False, 'sip'), + ('directory', 'user'): (None, 'jud'), + ('pubsub', 'generic'): (PubSubBrowser, 'pubsub'), + ('pubsub', 'service'): (PubSubBrowser, 'pubsub'), + ('proxy', 'bytestreams'): (None, 'bytestreams'), # Socks5 FT proxy + ('headline', 'newmail'): (ToplevelAgentBrowser, 'mail'), # Transports - ('conference', 'irc'): (ToplevelAgentBrowser, 'irc.png'), - ('_jid', 'irc'): (False, 'irc.png'), - ('gateway', 'aim'): (False, 'aim.png'), - ('_jid', 'aim'): (False, 'aim.png'), - ('gateway', 'gadu-gadu'): (False, 'gadu-gadu.png'), - ('_jid', 'gadugadu'): (False, 'gadu-gadu.png'), - ('gateway', 'http-ws'): (False, 'http-ws.png'), - ('gateway', 'icq'): (False, 'icq.png'), - ('_jid', 'icq'): (False, 'icq.png'), - ('gateway', 'msn'): (False, 'msn.png'), - ('_jid', 'msn'): (False, 'msn.png'), - ('gateway', 'sms'): (False, 'sms.png'), - ('_jid', 'sms'): (False, 'sms.png'), - ('gateway', 'smtp'): (False, 'mail.png'), - ('gateway', 'yahoo'): (False, 'yahoo.png'), - ('_jid', 'yahoo'): (False, 'yahoo.png'), - ('gateway', 'mrim'): (False, 'mrim.png'), - ('_jid', 'mrim'): (False, 'mrim.png'), - ('gateway', 'facebook'): (False, 'facebook.png'), - ('_jid', 'facebook'): (False, 'facebook.png'), + ('conference', 'irc'): (ToplevelAgentBrowser, 'irc'), + ('_jid', 'irc'): (False, 'irc'), + ('gateway', 'aim'): (False, 'aim'), + ('_jid', 'aim'): (False, 'aim'), + ('gateway', 'gadu-gadu'): (False, 'gadu_gadu'), + ('_jid', 'gadugadu'): (False, 'gadu_gadu'), + ('gateway', 'http-ws'): (False, 'http_ws'), + ('gateway', 'icq'): (False, 'icq'), + ('_jid', 'icq'): (False, 'icq'), + ('gateway', 'msn'): (False, 'msn'), + ('_jid', 'msn'): (False, 'msn'), + ('gateway', 'sms'): (False, 'sms'), + ('_jid', 'sms'): (False, 'sms'), + ('gateway', 'smtp'): (False, 'mail'), + ('gateway', 'yahoo'): (False, 'yahoo'), + ('_jid', 'yahoo'): (False, 'yahoo'), + ('gateway', 'mrim'): (False, 'mrim'), + ('_jid', 'mrim'): (False, 'mrim'), + ('gateway', 'facebook'): (False, 'facebook'), + ('_jid', 'facebook'): (False, 'facebook'), } # Category type to "human-readable" description string, and sort priority @@ -291,13 +291,12 @@ class ServicesCache: info = _agent_type_info[(0, 0)] filename = info[1] if not filename: # we don't have an image to show for this type - filename = 'jabber.png' + filename = 'jabber' # Use the cache if possible if filename in _icon_cache: return _icon_cache[filename] # Or load it - filepath = os.path.join(gajim.DATA_DIR, 'pixmaps', 'agents', filename) - pix = gtk.gdk.pixbuf_new_from_file(filepath) + pix = gtkgui_helpers.get_icon_pixmap('gajim-agent-' + filename, size=32) # Store in cache _icon_cache[filename] = pix return pix diff --git a/src/gajim.py b/src/gajim.py index a2e58f4e7..d0ed38f20 100644 --- a/src/gajim.py +++ b/src/gajim.py @@ -322,8 +322,7 @@ def pid_alive(): return True if pid_alive(): - path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps/gajim.png') - pix = gtk.gdk.pixbuf_new_from_file(path_to_file) + pix = gtkgui_helpers.get_icon_pixmap('gajim', 48) gtk.window_set_default_icon(pix) # set the icon to all newly opened wind pritext = _('Gajim is already running') sectext = _('Another instance of Gajim seems to be running\nRun anyway?') diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py index ac9fa157e..01ec5d605 100644 --- a/src/gtkgui_helpers.py +++ b/src/gtkgui_helpers.py @@ -82,6 +82,15 @@ def get_icon_path(icon_name, size=16): except gobject.GError, e: log.error("Unable to find icon %s: %s" % (icon_name, str(e))) +def add_image_to_menuitem(menuitem, icon_name): + img = gtk.Image() + path_img = get_icon_path(icon_name) + img.set_from_file(path_img) + menuitem.set_image(img) + +def add_image_to_button(button, icon_name): + add_image_to_menuitem(button, icon_name) + GLADE_DIR = os.path.join(gajim.DATA_DIR, 'glade') def get_glade(file_name, root = None): file_path = os.path.join(GLADE_DIR, file_name) diff --git a/src/gui_interface.py b/src/gui_interface.py index 859b9a9d1..337e53924 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -199,9 +199,7 @@ class Interface: def handle_event_connection_lost(self, account, array): # ('CONNECTION_LOST', account, [title, text]) - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'connection_lost.png') - path = gtkgui_helpers.get_path_to_generic_or_avatar(path) + path = gtkgui_helpers.get_icon_path('gajim-connection_lost', 48) notify.popup(_('Connection Failed'), account, account, 'connection_failed', path, array[0], array[1]) @@ -593,9 +591,7 @@ class Interface: self.add_event(account, jid, 'subscription_request', (text, nick)) if helpers.allow_showing_notification(account): - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'subscription_request.png') - path = gtkgui_helpers.get_path_to_generic_or_avatar(path) + path = gtkgui_helpers.get_icon_path('gajim-subscription_request', 48) event_type = _('Subscription request') notify.popup(event_type, jid, account, 'subscription_request', path, event_type, jid) @@ -653,13 +649,12 @@ class Interface: if helpers.allow_popup_window(account) or not self.systray_enabled: self.show_unsubscribed_dialog(account, contact) + return self.add_event(account, jid, 'unsubscribed', contact) if helpers.allow_showing_notification(account): - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'unsubscribed.png') - path = gtkgui_helpers.get_path_to_generic_or_avatar(path) + path = gtkgui_helpers.get_icon_path('gajim-unsubscribed', 48) event_type = _('Unsubscribed') notify.popup(event_type, jid, account, 'unsubscribed', path, event_type, jid) @@ -1117,9 +1112,7 @@ class Interface: array[3], array[4])) if helpers.allow_showing_notification(account): - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'gc_invitation.png') - path = gtkgui_helpers.get_path_to_generic_or_avatar(path) + path = gtkgui_helpers.get_icon_path('gajim-gc_invitation', 48) event_type = _('Groupchat Invitation') notify.popup(event_type, jid, account, 'gc-invitation', path, event_type, room_jid) @@ -1139,7 +1132,7 @@ class Interface: sectext += _('You are currently connected without your OpenPGP key.') dialogs.WarningDialog(_('Your passphrase is incorrect'), sectext) else: - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'warning.png') + path = gtkgui_helpers.get_icon_path('gajim-warning', 48) notify.popup('warning', account, account, 'warning', path, _('OpenGPG Passphrase Incorrect'), _('You are currently connected without your OpenPGP key.')) @@ -1276,8 +1269,7 @@ class Interface: self.add_event(account, jid, 'file-send-error', file_props) if helpers.allow_showing_notification(account): - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', 'ft_error.png') - path = gtkgui_helpers.get_path_to_generic_or_avatar(img) + path = gtkgui_helpers.get_icon_path('gajim-ft_error', 48) event_type = _('File Transfer Error') notify.popup(event_type, jid, account, 'file-send-error', path, event_type, file_props['name']) @@ -1287,8 +1279,7 @@ class Interface: gmail_new_messages = int(array[1]) gmail_messages_list = array[2] if gajim.config.get('notify_on_new_gmail_email'): - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'new_email_recv.png') + path = gtkgui_helpers.get_icon_path('gajim-new_email_recv', 48) title = _('New mail on %(gmail_mail_address)s') % \ {'gmail_mail_address': jid} text = i18n.ngettext('You have %d new mail conversation', @@ -1311,7 +1302,6 @@ class Interface: if gajim.config.get_per('soundevents', 'gmail_received', 'enabled'): helpers.play_sound('gmail_received') - path = gtkgui_helpers.get_path_to_generic_or_avatar(img) notify.popup(_('New E-mail'), jid, account, 'gmail', path_to_image=path, title=title, text=text) @@ -1343,9 +1333,7 @@ class Interface: if helpers.allow_showing_notification(account): # check if we should be notified - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', 'ft_error.png') - - path = gtkgui_helpers.get_path_to_generic_or_avatar(img) + path = gtkgui_helpers.get_icon_path('gajim-ft_error', 48) event_type = _('File Transfer Error') notify.popup(event_type, jid, account, msg_type, path, title = event_type, text = file_props['name']) @@ -1374,11 +1362,9 @@ class Interface: self.add_event(account, jid, 'file-request', file_props) if helpers.allow_showing_notification(account): - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'ft_request.png') + path = gtkgui_helpers.get_icon_path('gajim-ft_request', 48) txt = _('%s wants to send you a file.') % gajim.get_name_from_jid( account, jid) - path = gtkgui_helpers.get_path_to_generic_or_avatar(img) event_type = _('File Transfer Request') notify.popup(event_type, jid, account, 'file-request', path_to_image = path, title = event_type, text = txt) @@ -1449,11 +1435,11 @@ class Interface: if event_type == _('File Transfer Completed'): txt = _('You successfully received %(filename)s from %(name)s.')\ % {'filename': filename, 'name': name} - img = 'ft_done.png' + img_name = 'gajim-ft_done' else: # ft stopped txt = _('File transfer of %(filename)s from %(name)s stopped.')\ % {'filename': filename, 'name': name} - img = 'ft_stopped.png' + img_name = 'gajim-ft_stopped' else: receiver = file_props['receiver'] if hasattr(receiver, 'jid'): @@ -1466,23 +1452,23 @@ class Interface: if event_type == _('File Transfer Completed'): txt = _('You successfully sent %(filename)s to %(name)s.')\ % {'filename': filename, 'name': name} - img = 'ft_done.png' + img_name = 'gajim-ft_done' else: # ft stopped txt = _('File transfer of %(filename)s to %(name)s stopped.')\ % {'filename': filename, 'name': name} - img = 'ft_stopped.png' - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', img) - path = gtkgui_helpers.get_path_to_generic_or_avatar(img) + img_name = 'gajim-ft_stopped' + path = gtkgui_helpers.get_icon_path(img_name, 48) else: txt = '' + path = '' if gajim.config.get('notify_on_file_complete') and \ (gajim.config.get('autopopupaway') or \ gajim.connections[account].connected in (2, 3)): # we want to be notified and we are online/chat or we don't mind # bugged when away/na/busy - notify.popup(event_type, jid, account, msg_type, path_to_image = path, - title = event_type, text = txt) + notify.popup(event_type, jid, account, msg_type, path_to_image=path, + title=event_type, text=txt) def handle_event_stanza_arrived(self, account, stanza): if account not in self.instances: @@ -1766,11 +1752,9 @@ class Interface: if helpers.allow_showing_notification(account): # TODO: we should use another pixmap ;-) - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'ft_request.png') txt = _('%s wants to start a voice chat.') % gajim.get_name_from_jid( account, peerjid) - path = gtkgui_helpers.get_path_to_generic_or_avatar(img) + path = gtkgui_helpers.get_icon_path('gajim-mic_active', 48) event_type = _('Voice Chat Request') notify.popup(event_type, peerjid, account, 'jingle-incoming', path_to_image = path, title = event_type, text = txt) @@ -2778,8 +2762,8 @@ class Interface: if status in ('chat', 'away', 'xa', 'dnd', 'invisible', 'offline'): status = status + '.png' elif status == 'online': - prefix = os.path.join(gajim.DATA_DIR, 'pixmaps') - status = 'gajim.png' + prefix = '' + status = gtkgui_helpers.get_icon_path('gajim', 32) path = os.path.join(prefix, status) try: obj = bus.get_object('com.google.code.Awn', '/com/google/code/Awn') @@ -3382,8 +3366,7 @@ class Interface: import statusicon self.systray = statusicon.StatusIcon() - path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'gajim.png') - pix = gtk.gdk.pixbuf_new_from_file(path_to_file) + pix = gtkgui_helpers.get_icon_pixmap('gajim', 32) # set the icon to all windows gtk.window_set_default_icon(pix) diff --git a/src/gui_menu_builder.py b/src/gui_menu_builder.py index f18354175..5fd799a99 100644 --- a/src/gui_menu_builder.py +++ b/src/gui_menu_builder.py @@ -207,11 +207,7 @@ def get_contact_menu(contact, account, use_multiple_contacts=True, if not our_jid: # add a special img for rename menuitem - path_to_kbd_input_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'kbd_input.png') - img = gtk.Image() - img.set_from_file(path_to_kbd_input_img) - rename_menuitem.set_image(img) + gtkgui_helpers.add_image_to_menuitem(rename_menuitem, 'gajim-kbd_input') muc_icon = gtkgui_helpers.load_icon('muc_active') if muc_icon: diff --git a/src/history_manager.py b/src/history_manager.py index 5d171b75c..13dd22a62 100644 --- a/src/history_manager.py +++ b/src/history_manager.py @@ -102,19 +102,12 @@ C_NICKNAME ) = range(2, 6) -try: - import sqlite3 as sqlite # python 2.5 -except ImportError: - try: - from pysqlite2 import dbapi2 as sqlite - except ImportError: - raise exceptions.PysqliteNotAvailable +import sqlite3 as sqlite class HistoryManager: def __init__(self): - path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps/gajim.png') - pix = gtk.gdk.pixbuf_new_from_file(path_to_file) + pix = gtkgui_helpers.get_icon_pixmap('gajim') gtk.window_set_default_icon(pix) # set the icon to all newly opened windows if not os.path.exists(LOG_DB_PATH): diff --git a/src/htmltextview.py b/src/htmltextview.py index 8b65d8f87..35a289ebb 100644 --- a/src/htmltextview.py +++ b/src/htmltextview.py @@ -892,8 +892,10 @@ class HtmlTextView(gtk.TextView): def on_text_buffer_mark_set(self, location, mark, unused_data): bounds = self.get_buffer().get_selection_bounds() if bounds: - clipboard = self.get_clipboard(gtk.gdk.SELECTION_PRIMARY) - clipboard.set_text(self.get_selected_text()) + # textview can be hidden while we add a new line in it. + if self.has_screen(): + clipboard = self.get_clipboard(gtk.gdk.SELECTION_PRIMARY) + clipboard.set_text(self.get_selected_text()) def get_selected_text(self): bounds = self.get_buffer().get_selection_bounds() @@ -939,12 +941,12 @@ if __name__ == '__main__': htmlview = ConversationTextview(None) - path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'muc_separator.png') + path = gtkgui_helpers.get_icon_path('gajim-muc_separator') # use this for hr - htmlview.tv.focus_out_line_pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file) - + htmlview.tv.focus_out_line_pixbuf = gtk.gdk.pixbuf_new_from_file(path) tooltip = tooltips.BaseTooltip() + def on_textview_motion_notify_event(widget, event): """ Change the cursor to a hand when we are over a mail or an url diff --git a/src/notify.py b/src/notify.py index 587c4e292..37a7fd267 100644 --- a/src/notify.py +++ b/src/notify.py @@ -234,16 +234,16 @@ def notify(event, jid, account, parameters, advanced_notif_num=None): show_image = 'online.png' suffix = '_notif_size_colored' transport_name = gajim.get_transport_name_from_jid(jid) - img = None + img_path = None if transport_name: - img = os.path.join(helpers.get_transport_path(transport_name), + img_path = os.path.join(helpers.get_transport_path(transport_name), '48x48', show_image) - if not img or not os.path.isfile(img): + if not img_path or not os.path.isfile(img_path): iconset = gajim.config.get('iconset') - img = os.path.join(helpers.get_iconset_path(iconset), '48x48', + img_path = os.path.join(helpers.get_iconset_path(iconset), '48x48', show_image) - path = gtkgui_helpers.get_path_to_generic_or_avatar(img, - jid = jid, suffix = suffix) + path = gtkgui_helpers.get_path_to_generic_or_avatar(img_path, jid=jid, + suffix=suffix) if event == 'status_change': title = _('%(nick)s Changed Status') % \ {'nick': gajim.get_name_from_jid(account, jid)} @@ -273,16 +273,14 @@ def notify(event, jid, account, parameters, advanced_notif_num=None): elif event == 'new_message': if message_type == 'normal': # single message event_type = _('New Single Message') - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'single_msg_recv.png') + img_name = 'gajim-single_msg_recv' title = _('New Single Message from %(nickname)s') % \ {'nickname': nickname} text = message elif message_type == 'pm': # private message event_type = _('New Private Message') room_name = gajim.get_nick_from_jid(jid) - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'priv_msg_recv.png') + img_name = 'gajim-priv_msg_recv' title = _('New Private Message from group chat %s') % room_name if message: text = _('%(nickname)s: %(message)s') % {'nickname': nickname, @@ -292,14 +290,13 @@ def notify(event, jid, account, parameters, advanced_notif_num=None): else: # chat message event_type = _('New Message') - img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'chat_msg_recv.png') + img_name = 'gajim-chat_msg_recv' title = _('New Message from %(nickname)s') % \ {'nickname': nickname} text = message - path = gtkgui_helpers.get_path_to_generic_or_avatar(img) + img_path = gtkgui_helpers.get_icon_path(img_name, 48) popup(event_type, jid, account, message_type, - path_to_image=path, title=title, text=text) + path_to_image=img_path, title=title, text=text) if do_sound: snd_file = None @@ -342,9 +339,7 @@ def popup(event_type, jid, account, msg_type='', path_to_image=None, title=None, """ # default image if not path_to_image: - path_to_image = os.path.abspath( - os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'chat_msg_recv.png')) # img to display + path_to_image = gtkgui_helpers.get_icon_path('gajim-chat_msg_recv', 48) if gajim.HAVE_INDICATOR and event_type in (_('New Message'), _('New Single Message'), _('New Private Message')): @@ -529,9 +524,8 @@ class DesktopNotification: ntype = 'unsubscribed' else: # default failsafe values - self.path_to_image = os.path.abspath( - os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', - 'chat_msg_recv.png')) # img to display + self.path_to_image = gtkgui_helpers.get_icon_path( + 'gajim-chat_msg_recv', 48) ntype = 'im' # Notification Type self.notif = dbus_support.get_notifications_interface(self) @@ -554,8 +548,7 @@ class DesktopNotification: notification_text = ('' \ '%(title)s
%(text)s') % {'title': self.title, 'text': self.text, 'image': self.path_to_image} - gajim_icon = os.path.abspath(os.path.join(gajim.DATA_DIR, 'pixmaps', - 'gajim.png')) + gajim_icon = gtkgui_helpers.get_icon_path('gajim', 48) self.notif.Notify( dbus.String(_('Gajim')), # app_name (string) dbus.UInt32(0), # replaces_id (uint) diff --git a/src/roster_window.py b/src/roster_window.py index 50249d642..9e56d3c97 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -4962,10 +4962,7 @@ class RosterWindow: sub_menu.append(item) item = gtk.ImageMenuItem(_('_Change Status Message')) - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'kbd_input.png') - img = gtk.Image() - img.set_from_file(path) - item.set_image(img) + gtkgui_helpers.add_image_to_menuitem(item, 'gajim-kbd_input') sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate, account) @@ -5063,10 +5060,7 @@ class RosterWindow: sub_menu.append(item) item = gtk.ImageMenuItem(_('_Change Status Message')) - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'kbd_input.png') - img = gtk.Image() - img.set_from_file(path) - item.set_image(img) + gtkgui_helpers.add_image_to_menuitem(item, 'gajim-kbd_input') sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate, account) @@ -5219,11 +5213,7 @@ class RosterWindow: # Rename rename_item = gtk.ImageMenuItem(_('Re_name')) # add a special img for rename menuitem - path_to_kbd_input_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'kbd_input.png') - img = gtk.Image() - img.set_from_file(path_to_kbd_input_img) - rename_item.set_image(img) + gtkgui_helpers.add_image_to_menuitem(rename_item, 'gajim-kbd_input') menu.append(rename_item) rename_item.connect('activate', self.on_rename, 'group', group, account) @@ -5481,11 +5471,7 @@ class RosterWindow: # Rename item = gtk.ImageMenuItem(_('_Rename')) # add a special img for rename menuitem - path_to_kbd_input_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'kbd_input.png') - img = gtk.Image() - img.set_from_file(path_to_kbd_input_img) - item.set_image(img) + gtkgui_helpers.add_image_to_menuitem(item, 'gajim-kbd_input') manage_transport_submenu.append(item) item.connect('activate', self.on_rename, 'agent', jid, account) if gajim.account_is_disconnected(account): @@ -5813,7 +5799,7 @@ class RosterWindow: # Add a Separator (self._iter_is_separator() checks on string SEPARATOR) liststore.append(['SEPARATOR', None, '', True]) - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'kbd_input.png') + path = gtkgui_helpers.get_icon_path('gajim-kbd_input') img = gtk.Image() img.set_from_file(path) # sensitivity to False because by default we're offline diff --git a/src/statusicon.py b/src/statusicon.py index 556fb9fa1..33c3fa063 100644 --- a/src/statusicon.py +++ b/src/statusicon.py @@ -207,10 +207,7 @@ class StatusIcon: sub_menu.append(item) item = gtk.ImageMenuItem(_('_Change Status Message...')) - path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'kbd_input.png') - img = gtk.Image() - img.set_from_file(path) - item.set_image(img) + gtkgui_helpers.add_image_to_menuitem(item, 'gajim-kbd_input') sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate)