diff --git a/AUTHORS b/AUTHORS
index 29f8040f0..b3dd37b13 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,6 +1,7 @@
CURRENT DEVELOPERS:
Yann Le Boulanger (asterix AT lagaule.org)
+Nikos Kouremenos (kourem AT gmail.com)
Dimitur Kirov (dkirov AT gmail.com)
Travis Shirk (travis AT pobox.com)
Jean-Marie Traissard (jim AT lapin.org)
@@ -8,4 +9,3 @@ Jean-Marie Traissard (jim AT lapin.org)
PAST DEVELOPERS:
Vincent Hanquez (tab AT snarc.org)
-Nikos Kouremenos (kourem AT gmail.com)
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index f21490300..000000000
--- a/ChangeLog
+++ /dev/null
@@ -1,208 +0,0 @@
-Gajim 0.11 (XX October 2006)
-
- * Put your stuff here [each dev put their own please; next time we do this everytime we commit sth major and not in the end]
-
- * We can now operate on more than one contact in one in time in roster (#1514)
- * Connection lost is now a non-intrusive popup
- * Try to get contact desired nick when we add him to roster aka User Nickname (JEP-0172)
- * Better design of User Profile window, with a progress bar
- * New Add User dialog, with possibility to register to transport directly from it
- * Completion for "Start Chat" input dialog
- * We can now have a different spellchecking language in each chat window. (#2383 and #746)
- * Support for Privacy Lists
- * Forbid to run multiple instances (but you can use differents profiles)
- * We can save avatar with right click on avatar in chat banner
- * Use differents colors for nickname colors of occupants in groupchats.
- * Ability to show only Join/Leave in groupchats instead of all status changes
- * New possibilities to insert nickname of an occupant in groupchats conversations : Tab in an empty line now cycle through nicks, maj+right click->insert nickname, maj+click on name in gc-roster, /names command to show all users presents
-
- * Fixed bugs when removing or renaming an account with tabs open (#2369 and #2370)
-
- * FIXME : Ad-Hoc for 0.11 ?
- * FIXME : does that work ? not tested : Metacontacts across accounts (#1596)
- * Gajim now requires Python 2.4 to run
-
-Gajim 0.10.1 (06 June 2006)
-
- * Freeze and lost contacts in roster (#1953)
- * Popup menus are correctly placed
- * High CPU usage on FreeBSD (#1963)
- * Nickname can contain '|' (#1913)
- * Update pl, cs, fr translations
- * Don't play sound, when no event is shown (#1970)
- * Set gajim icon for history manager
- * gajim.desktop is generated with translation (#834)
- * Preventing several TBs and annoyances (r6273, r6275, r6279, r6301,
- r6308, r6311, r6323, r6326, r6327, r6335, r6342, r6346, r6348)
-
-Gajim 0.10 (01 May 2006)
-
- * One Messages Window ability (default to it) with tab reordering ability
- * Non blocking socket connections. Gajim no longer remains unresponsive.
- * Gajim now uses less memory
- * File Transfer improvements (now should work out of the box for all)
- * Meta Contacts ability (relationships between contacts)
- * Support for legacy composing event (JEP-0022). Now 'Contact is composing a message' will always work
- * Gajim now defaults to theme that uses GTK colors
- * Roster Management Improvements (f.e. editablity of transport names, extended Drag and Drop Functionality)
- * History (chat logs) Manager (search globally, delete, etc)
- * Animated Emoticons ability
- * Support for GTalk email notifications for GMail
- * Room administrators can modify room ban list
- * Gajim no longer optionally depends on pydns or dnspython. Requires
- dnsutils (or whatever package provides the nslookup binary)
- * gajim-remote has extended functionality
- * Improved Preset Status Messages Experience
- * Detection for CRUX as user's operating system
- * New art included, appropriate sizes of icons used where available
- * Translations under Windows now work okay
- * Tons of fixes for bugs and annoyances: http://trac.gajim.org/query?status=closed&milestone=0.10
-
-
-Gajim 0.9.1 (27 December 2005)
-
- * Fix bug when joining a Groupchat
- * Fix bug when starting Gajim without old logs
-
-Gajim 0.9 (23 December 2005)
-
- * Avatars and status messages in roster window
- * Improved service discovery window
- * Emoticons selector, Cooler Popup Windows (notification-daemon). Read more information in case you did not notice something different in http://trac.gajim.org/wiki/GajimDBus#notif_daemon
- * Caching of Avatars, Less UI freezing
- * New Account creation wizard
- * Better History Window with searching capabilities
- * Gajim now tries to reconnect to a jabber server if connection is lost
- * Queue for all events (File Transfer, private messages, etc)
- * A lot of new irc-like commands in group chat. Do for example /help invite
- * X11 Session Management support
- * Gajim registers and handles xmpp: and xmpp:// (GNOME/gconfd only)
- * Use pysqlite for conversation history. Automigration for old logs
- * New translations: Italian, Swedish, Slovak, Basque
-
-Gajim 0.8.2 (06 Sep 2005)
-
- * Fix so Gajim runs in pygtk2.8.x
- * Gajim can use pydns too (apart from dnspython) to do SRV lookup
- * Other minor fixes
-
-Gajim 0.8.1 (02 Sep 2005)
-
- * Systray icon for windows
- * Gajim is available in Dutch
- * Gajim can use gpg-agent
-
-Gajim 0.8 (18 Aug 2005)
-
- * Avatars (JEP-0153)
- * Chat state notifications aka. typing notification (JEP-0085)
- * Bookmark storage (JEP-0048)
- * File Transfer (JEP-0096)
- * Major changes to adhere to GNOME HIG
- * Complete vcard fields support
- * New and better user interface for chat and groupchat windows
- * SRV capabilities and custom hostname/port
- * Many improvements in group chat and IRC emulation (eg. nick autocompletation and cycling)
- * Gajim can now send and receive single messages
- * New iconsets and new dialog for customizing the user interface
- * Mouseover information for contacts in the roster window (aka tooltips)
- * DBus Capabilities. Now Gajim can be remote controlled
- * Authenticating HTTP Requests via XMPP (JEP-0070)
- * Now you can lookup a word in Wikipedia, dictionary or in search engine
- * XML Console
- * Gajim is now also available in norwegian and czech language
-
-
-Gajim 0.7.1 (5 Jun 2005)
-
- * Transports icon as an option and error/mesage icon for transports
- * Gajim is more HIG compatible
- * Editing registration information on transports
- * Messages stanza without
element are not printed
- * SASL bugfix
- * GtkSpell capabilities
- * Support SSL (legacy) connection
- * Assign gpg key to specific contact
- * Contacts are sortable by status
- * Gajim remembers last lines when reopening chat
- * New translations available: German, Russian, Spanish, Bulgarian
-
-Gajim 0.7 (23 May 2005)
-
- * Ability for groupchat reserved rooms with full affiliations and roles support
- * Popup notification for incoming events
- * Protocol icons for contacts from transports
- * Gajim's user interface is now more HIG compliant
- * Gajim now detects and can send operating system information
- * Gajim now can inform the user about new version availability
- * Gajim jabber library migration from jabberpy to xmpppy
- * Rewrite the plugin system to remove threads and improve latency
- * Gajim now supports Nodes in Service Discovery
- * Greek and Polish translations
-
-
-Gajim 0.6.1 (03 April 2005)
-
- * Rewrite of service discovery. It doesn't freeze Gajim anymore.
- * More HIG Compliant.
- * Gajim is faster (do not redraw preferences_window each time we open it, use
- of psyco if available)
-
-Gajim 0.6 (23 March 2005)
-
- * Gajim's user interface is now nicer.
- * Groupchat just got better.
- * URL, mailto and ascii formatin (* / _) detection
- * Better transports detection, group management, and many minor additions/bugfixes
-
-Gajim 0.5.1 (27 February 2005)
-
- * Minor bugfixes.
-
-Gajim 0.5 (26 February 2005)
-
- * Possibility to use tabbed chat window
- * Sound support under GNU/linux
- * Autoaway available under Microsoft Windows
-
-Gajim 0.4.1 (23 January 2005)
-
- * Bugfix in config file parser (fix config file parser to handle emoticons)
- * Bugfix with GPG signatures
-
-Gajim 0.4 (21 January 2005)
-
- * New option: regroup accounts
- * Emoticons support with a binder
- * GUI improvements
- * Bugfixes
-
-Gajim 0.3 (18 December 2004)
-
- * GUI improvements
- * group chat support with MUC (JEP 45)
- * New agent browser (JEP 30)
- * GnuPG support
- * Autoconnect at startup
- * New socket plugin
-
-Gajim 0.2.1 (1 July 2004)
-
- * bugfixes : when configfile is incomplete
- * icon in systray with popup menu (for linux)
- * "auto away even if not online" option
- * always show contacts with unread messages
- * new imageCellRenderer to show animated gifs
- * allow agents unregistration
-
-Gajim 0.2 (8 June 2004)
-
- * bugfix for french translation
- * multi-resource support
- * auto away support (for linux)
- * invisible support
- * priority support
-
-Gajim 0.1 (21 May 2004)
-
- * Initial release.
diff --git a/Changelog b/Changelog
index f21490300..cf890cd9c 100644
--- a/Changelog
+++ b/Changelog
@@ -1,17 +1,19 @@
Gajim 0.11 (XX October 2006)
- * Put your stuff here [each dev put their own please; next time we do this everytime we commit sth major and not in the end]
-
- * We can now operate on more than one contact in one in time in roster (#1514)
+ * Intoducing View Menu (GNOME HIG)
+ * GNOME Keyring Support (if GNOME keyring available, manage passwords and save them in an encrypted file).
+ * Ability to now hide the Transports group
+ * Support for notify-python so if notification-daemon is not available, we still can show cool popups
+ * Ability to operate on more than one contact in one in time in roster (#1514)
* Connection lost is now a non-intrusive popup
* Try to get contact desired nick when we add him to roster aka User Nickname (JEP-0172)
* Better design of User Profile window, with a progress bar
* New Add User dialog, with possibility to register to transport directly from it
* Completion for "Start Chat" input dialog
- * We can now have a different spellchecking language in each chat window. (#2383 and #746)
+ * Ability to have a different spellchecking language in each chat window. (#2383 and #746)
* Support for Privacy Lists
* Forbid to run multiple instances (but you can use differents profiles)
- * We can save avatar with right click on avatar in chat banner
+ * Ability to save avatar with right click on avatar in chat banner
* Use differents colors for nickname colors of occupants in groupchats.
* Ability to show only Join/Leave in groupchats instead of all status changes
* New possibilities to insert nickname of an occupant in groupchats conversations : Tab in an empty line now cycle through nicks, maj+right click->insert nickname, maj+click on name in gc-roster, /names command to show all users presents
diff --git a/README b/README
index 49fdbefff..87b9af82a 100644
--- a/README
+++ b/README
@@ -1,85 +1 @@
-Welcome and thanks for trying out Gajim.
-
-=RUNTIME REQUIREMENTS=
-python2.4 or higher
-pygtk2.6 or higher
-python-libglade
-pysqlite2 (if you have python 2.5, you already have this)
-
-some distros also split too much python standard library.
-I know SUSE does. In such distros you also need python-xml
-the xml lib that *comes* with python and not pyxml or whatever
-
-=COMPILE-TIME REQUIREMENTS=
-python-dev
-python-gtk2-dev
-libgtk2.0-dev # aka. gtk2-devel
-libxss-dev # for idle detection module (Some distributions (f.e. Debian) split xscreensaver)
-libgtkspell-dev # for gtkspell module
-intltool
-
-NOTE:
-if you still have problems compiling, you may want to try removing the gtk1 series of the above dependencies
-
-Optionally:
-dnsutils (or whatever package provides the nslookup binary) for SRV support; if you don't know what that is, you don't need it
-gtkspell and aspell-LANG where lang is your locale eg. en, fr etc
-GnomePythonExtras 2.10 or above so you can avoid compiling trayicon and gtkspell
-notification-daemon or notify-python (and D-Bus) to get cooler popups
-D-Bus to have gajim-remote working
-
-NOTE TO PACKAGERS:
-Gajim is a GTK+ app and not a gnome one.
-Just do 'make' so you don't require gnomepythonextras
-which is gnome dep
-
-=INSTALLATION PROCEDURE=
-tar jxvf gajim-version.tar.bz2
-cd gajim
-make # builds all modules
-su -c make install
-
-To specify what modules to build do:
-make help
-
-To specify where to install do:
-su -c make PREFIX=custom_path install
-
-=RUNNING GAJIM=
-gajim
-
-or if you didn't 'make install' you can also run from gajim folder with
-./launch.sh
-
-Last but not least, you can run Gajim from your GNOME/XFCE/KDE/whatever menus.
-
-=UNINSTALLATION PROCEDURE=
-su -c make uninstall
-this will try to remove Gajim from the default directories.
-If you want to remove it from custom directory provide it as:
-make PREFIX=custom_path uninstall
-
-=MISCELLANEOUS=
-XML & Debugging:
-If you want to see the xml stanzas and/or help us debugging
-you're advised to enable verbose via advanced configuration window.
-If you don't want to make this permanent, execute gajim with --verbose
-everytime you want to have verbose output.
-
-=FAQ/Wiki=
-FAQ can be found at http://trac.gajim.org/wiki/GajimFaq
-Wiki can be found at http://trac.gajim.org/wiki
-
-
-That is all, enjoy!
-
-(C) 2003-2006
-The Gajim Team
-http://gajim.org
-
-
-PS.
-We use original art and parts of sounds and other art from Psi, Gossip,
-Gnomebaker, Gaim and some icons from various gnome-icons
-(mostly Dropline Etiquette) we found at art.gnome.org
-If you think we're violating a license please inform us. Thank you
+see README.html
diff --git a/README.html b/README.html
new file mode 100644
index 000000000..3be3024eb
--- /dev/null
+++ b/README.html
@@ -0,0 +1,130 @@
+
+
+
+ Gajim - Read Me
+
+
+
+Gajim Read Me
+
+
+Welcome to Gajim and thank you for trying out our client.
+
+
+Runtime Requirements
+
+- python2.4 or higher
+- pygtk2.6 or higher
+- python-libglade
+- pysqlite2 (if you have python 2.5, you already have this)
+
+
+
+Note to packagers
+Gajim is a GTK+ app that loves GNOME. You can do 'make' so you don't require gnomepythonextras (aka gnome-python-desktop) which is gnome dep, but you will miss gnomekeyring intergration.
+
+
+Optional Runtime Requirements
+
+- dnsutils (or whatever package provides the nslookup binary) for SRV support; if you don't know what that is, you don't need it
+- gtkspell and aspell-LANG where lang is your locale eg. en, fr etc
+- GnomePythonExtras 2.10 or above (aka gnome-python-desktop) so you can avoid compiling trayicon and gtkspell
+- gnome-python-desktop (for GnomeKeyring support)
+- notification-daemon or notify-python (and D-Bus) to get cooler popups
+- D-Bus to have gajim-remote working
+
+
+
+Some distributions also split too much python standard library.
+I know SUSE does. In such distros you also need python-xml
+the xml lib that *comes* with python and not pyxml or whatever.
+
+
+Compile-time Requirements
+
+- python-dev
+- python-gtk2-dev
+- libgtk2.0-dev aka. gtk2-devel
+- libxss-dev (for idle detection module; some distributions such as Debian split xscreensaver)
+- libgtkspell-dev (for the gtkspell module)
+- intltool
+
+
+
+NOTE:
+If you still have problems compiling, you may want to try removing the gtk1 series of the above dependencies.
+
+
+Installation Procedure
+
+- tar jxvf gajim-version.tar.bz2
+cd gajim
+make (builds all modules)
+su -c make install
+
+
+
+To specify what modules to build do:
+make help
+
+
+
+To specify where to install do:
+su -c make PREFIX=custom_path install
+
+
+Running Gajim
+
+Just do gajim or you can run Gajim from your GNOME/XFCE/KDE/whatever menus.
+
+or if you didn't 'make install' you can also run from gajim folder with
+./launch.sh
+
+
+Uninstallation Procedure
+
+su -c make uninstall
+this will try to remove Gajim from the default directories.
+If you want to remove it from custom directory provide it as:
+make PREFIX=custom_path uninstall
+
+
+Miscellaneous
+XML & Debugging
+
+If you want to see the xml stanzas and/or help us debugging
+you're advised to enable verbose via advanced configuration window.
+If you don't want to make this permanent, execute gajim with --verbose
+everytime you want to have verbose output.
+
+
+FAQ/Wiki
+
+FAQ can be found at http://trac.gajim.org/wiki/GajimFaq
+Wiki can be found at http://trac.gajim.org/wiki
+
+
+
+
+That is all, enjoy!
+
+
+
+
+
+
+(C) 2003-2006
+The Gajim Team
+http://gajim.org
+
+
+
+PS.
+We use original art and parts of sounds and other art from Psi, Gossip,
+Gnomebaker, Gaim and some icons from various gnome-icons
+(mostly Dropline Etiquette) we found at art.gnome.org
+If you think we're violating a license please inform us. Thank you.
+
+
diff --git a/data/glade/join_groupchat_window.glade b/data/glade/join_groupchat_window.glade
index e6960a86a..618dff121 100644
--- a/data/glade/join_groupchat_window.glade
+++ b/data/glade/join_groupchat_window.glade
@@ -17,6 +17,7 @@
GDK_WINDOW_TYPE_HINT_NORMAL
GDK_GRAVITY_NORTH_WEST
True
+ False
@@ -29,58 +30,14 @@
True
- 5
+ 4
2
False
6
12
-
- True
- True
- True
- False
- 0
-
- True
- *
- True
-
-
- 1
- 2
- 4
- 5
-
-
-
-
-
-
- True
- True
- True
- True
- 0
-
- True
- *
- True
-
-
-
-
- 1
- 2
- 3
- 4
-
-
-
-
-
-
+
True
True
True
@@ -91,7 +48,6 @@
True
*
True
-
@@ -125,62 +81,6 @@
-
-
- True
- Password:
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- 1
- 4
- 5
- fill
-
-
-
-
-
-
- True
- Server:
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- 1
- 3
- 4
- fill
-
-
-
-
True
@@ -281,6 +181,55 @@
fill
+
+
+
+ True
+ Password:
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0
+ 0.5
+ 0
+ 0
+ PANGO_ELLIPSIZE_NONE
+ -1
+ False
+ 0
+
+
+ 0
+ 1
+ 3
+ 4
+ fill
+
+
+
+
+
+
+ True
+ True
+ True
+ False
+ 0
+
+ True
+ *
+ True
+
+
+ 1
+ 2
+ 3
+ 4
+
+
+
0
diff --git a/data/glade/preferences_window.glade b/data/glade/preferences_window.glade
index 573c182a8..d9d2165ce 100644
--- a/data/glade/preferences_window.glade
+++ b/data/glade/preferences_window.glade
@@ -900,7 +900,6 @@ Per type
True
True
- Επιλογή μιας γραμματοσειράς
True
True
False
@@ -952,7 +951,6 @@ Per type
True
True
False
- Επιλογή χρώματος
True
@@ -971,7 +969,6 @@ Per type
True
True
False
- Επιλογή χρώματος
True
@@ -1051,7 +1048,6 @@ Per type
True
True
False
- Επιλογή χρώματος
True
@@ -1070,7 +1066,6 @@ Per type
True
True
False
- Επιλογή χρώματος
True
diff --git a/data/glade/vcard_information_window.glade b/data/glade/vcard_information_window.glade
index 3b88416c0..f677804ff 100644
--- a/data/glade/vcard_information_window.glade
+++ b/data/glade/vcard_information_window.glade
@@ -448,7 +448,7 @@
-
+
True
Subscription:
False
@@ -476,7 +476,7 @@
-
+
True
Ask:
False
diff --git a/po/POTFILES.in b/po/POTFILES.in
deleted file mode 100644
index 5bf9ba2c6..000000000
--- a/po/POTFILES.in
+++ /dev/null
@@ -1,114 +0,0 @@
-# ls data/gajim.desktop.in.in data/glade/*.glade src/*py
-# src/common/*py src/common/zeroconf/*.py -1 -U
-# to produce this list
-
-[encoding: UTF-8]
-data/gajim.desktop.in.in
-data/glade/account_context_menu.glade
-data/glade/account_creation_wizard_window.glade
-data/glade/account_modification_window.glade
-data/glade/accounts_window.glade
-data/glade/add_new_contact_window.glade
-data/glade/advanced_configuration_window.glade
-data/glade/advanced_menuitem_menu.glade
-data/glade/advanced_notifications_window.glade
-data/glade/change_password_dialog.glade
-data/glade/change_status_message_dialog.glade
-data/glade/chat_context_menu.glade
-data/glade/chat_control_popup_menu.glade
-data/glade/choose_gpg_key_dialog.glade
-data/glade/data_form_window.glade
-data/glade/edit_groups_dialog.glade
-data/glade/filetransfers.glade
-data/glade/gajim_themes_window.glade
-data/glade/gc_control_popup_menu.glade
-data/glade/gc_occupants_menu.glade
-data/glade/history_manager.glade
-data/glade/history_window.glade
-data/glade/input_dialog.glade
-data/glade/invitation_received_dialog.glade
-data/glade/join_groupchat_window.glade
-data/glade/manage_accounts_window.glade
-data/glade/manage_bookmarks_window.glade
-data/glade/manage_proxies_window.glade
-data/glade/message_window.glade
-data/glade/passphrase_dialog.glade
-data/glade/popup_notification_window.glade
-data/glade/preferences_window.glade
-data/glade/privacy_lists_window.glade
-data/glade/privacy_list_window.glade
-data/glade/profile_window.glade
-data/glade/progress_dialog.glade
-data/glade/remove_account_window.glade
-data/glade/roster_contact_context_menu.glade
-data/glade/roster_window.glade
-data/glade/service_discovery_window.glade
-data/glade/service_registration_window.glade
-data/glade/single_message_window.glade
-data/glade/subscription_request_popup_menu.glade
-data/glade/subscription_request_window.glade
-data/glade/systray_context_menu.glade
-data/glade/vcard_information_window.glade
-data/glade/xml_console_window.glade
-data/glade/zeroconf_contact_context_menu.glade
-data/glade/zeroconf_context_menu.glade
-data/glade/zeroconf_information_window.glade
-data/glade/zeroconf_properties_window.glade
-src/advanced.py
-src/cell_renderer_image.py
-src/chat_control.py
-src/config.py
-src/conversation_textview.py
-src/dbus_support.py
-src/dialogs.py
-src/disco.py
-src/filetransfers_window.py
-src/gajim.py
-src/gajim-remote.py
-src/gajim_themes_window.py
-src/groupchat_control.py
-src/gtkexcepthook.py
-src/gtkgui_helpers.py
-src/history_manager.py
-src/history_window.py
-src/htmltextview.py
-src/message_control.py
-src/message_textview.py
-src/message_window.py
-src/music_track_listener.py
-src/notify.py
-src/profile_window.py
-src/remote_control.py
-src/roster_window.py
-src/rst_xhtml_generator.py
-src/systray.py
-src/systraywin32.py
-src/tooltips.py
-src/vcard.py
-src/common/check_paths.py
-src/common/config.py
-src/common/connection_handlers.py
-src/common/connection.py
-src/common/contacts.py
-src/common/dbus_support.py
-src/common/events.py
-src/common/exceptions.py
-src/common/fuzzyclock.py
-src/common/gajim.py
-src/common/GnuPGInterface.py
-src/common/GnuPG.py
-src/common/helpers.py
-src/common/i18n.py
-src/common/__init__.py
-src/common/logger.py
-src/common/nslookup.py
-src/common/optparser.py
-src/common/proxy65_manager.py
-src/common/sleepy.py
-src/common/socks5.py
-src/common/xmpp_stringprep.py
-src/common/zeroconf/client_zeroconf.py
-src/common/zeroconf/connection_handlers_zeroconf.py
-src/common/zeroconf/connection_zeroconf.py
-src/common/zeroconf/__init__.py
-src/common/zeroconf/roster_zeroconf.py
diff --git a/po/de.po b/po/de.po
index 0c265fdc8..226bdd27e 100644
--- a/po/de.po
+++ b/po/de.po
@@ -373,7 +373,7 @@ msgstr "Konto-Status mit globalem Status abgleichen"
#: ../data/glade/account_modification_window.glade.h:40
msgid "Use _SSL (legacy)"
-msgstr "_SSL verwenden"
+msgstr "_SSL verwenden (veraltet)"
#: ../data/glade/account_modification_window.glade.h:41
msgid "Use custom hostname/port"
@@ -4485,7 +4485,7 @@ msgstr "für Konto %s"
#. History manager
#: ../src/roster_window.py:933
msgid "History Manager"
-msgstr "Verlaufmanager"
+msgstr "Verlaufsmanager"
#: ../src/roster_window.py:942
msgid "_Join New Room"
diff --git a/src/advanced.py b/src/advanced.py
index c0b8df496..0640c02d7 100644
--- a/src/advanced.py
+++ b/src/advanced.py
@@ -1,18 +1,8 @@
## advanced.py
##
-## Contributors for this file:
-## - Yann Le Boulanger
-## - Nikos Kouremenos
-## - Vincent Hanquez
-##
-## Copyright (C) 2003-2004 Yann Le Boulanger
-## Vincent Hanquez
-## Copyright (C) 2005 Yann Le Boulanger
-## Vincent Hanquez
-## Nikos Kouremenos
-## Dimitur Kirov
-## Travis Shirk
-## Norman Rasmussen
+## Copyright (C) 2005-2006 Yann Le Boulanger
+## Copyright (C) 2005-2006 Nikos Kouremenos
+## Copyright (C) 2005 Vincent Hanquez
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
@@ -42,7 +32,7 @@ C_TYPE
GTKGUI_GLADE = 'manage_accounts_window.glade'
-class AdvancedConfigurationWindow:
+class AdvancedConfigurationWindow(object):
def __init__(self):
self.xml = gtkgui_helpers.get_glade('advanced_configuration_window.glade')
self.window = self.xml.get_widget('advanced_configuration_window')
diff --git a/src/chat_control.py b/src/chat_control.py
index 9c5e33efa..4b4592f8d 100644
--- a/src/chat_control.py
+++ b/src/chat_control.py
@@ -34,7 +34,7 @@ from message_textview import MessageTextView
from common.contacts import GC_Contact
from common.logger import Constants
constants = Constants()
-from rst_xhtml_generator import create_xhtml
+from common.rst_xhtml_generator import create_xhtml
from common.xmpp.protocol import NS_XHTML
try:
@@ -1045,7 +1045,7 @@ class ChatControl(ChatControlBase):
status = contact.status
if status is not None:
banner_name_label.set_ellipsize(pango.ELLIPSIZE_END)
- status = gtkgui_helpers.reduce_chars_newlines(status, max_lines = 2)
+ status = helpers.reduce_chars_newlines(status, max_lines = 2)
status_escaped = gtkgui_helpers.escape_for_pango_markup(status)
font_attrs, font_attrs_small = self.get_font_attrs()
@@ -1254,7 +1254,9 @@ class ChatControl(ChatControlBase):
kind = 'outgoing'
name = gajim.nicks[self.account]
if not xhtml and not encrypted and gajim.config.get('rst_formatting_outgoing_messages'):
- xhtml = '%s' % (NS_XHTML, create_xhtml(text))
+ xhtml = create_xhtml(text)
+ if xhtml:
+ xhtml = '%s' % (NS_XHTML, xhtml)
ChatControlBase.print_conversation_line(self, text, kind, name, tim,
subject = subject, old_kind = self.old_msg_kind, xhtml = xhtml)
if text.startswith('/me ') or text.startswith('/me\n'):
@@ -1674,7 +1676,7 @@ class ChatControl(ChatControlBase):
else:
kind = 'print_queue'
self.print_conversation(data[0], kind, tim = data[3],
- encrypted = data[4], subject = data[1])
+ encrypted = data[4], subject = data[1], xhtml = data[7])
if len(data) > 6 and isinstance(data[6], int):
message_ids.append(data[6])
if message_ids:
diff --git a/src/common/check_paths.py b/src/common/check_paths.py
index a6bc52bf1..a504c054d 100644
--- a/src/common/check_paths.py
+++ b/src/common/check_paths.py
@@ -1,16 +1,7 @@
-## Contributors for this file:
-## - Yann Le Boulanger
-## - Nikos Kouremenos
-## - Travis Shirk
##
-## Copyright (C) 2003-2004 Yann Le Boulanger
-## Vincent Hanquez
-## Copyright (C) 2005 Yann Le Boulanger
-## Vincent Hanquez
-## Nikos Kouremenos
-## Dimitur Kirov
-## Travis Shirk
-## Norman Rasmussen
+## Copyright (C) 2005-2006 Yann Le Boulanger
+## Copyright (C) 2005-2006 Nikos Kouremenos
+## Copyright (C) 2005-2006 Travis Shirk
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
@@ -57,11 +48,13 @@ def create_log_db():
jid_id INTEGER
);
+ CREATE INDEX idx_unread_messages_jid_id ON unread_messages (jid_id);
+
CREATE TABLE transports_cache (
transport TEXT UNIQUE,
type INTEGER
);
-
+
CREATE TABLE logs(
log_line_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid_id INTEGER,
@@ -72,6 +65,8 @@ def create_log_db():
message TEXT,
subject TEXT
);
+
+ CREATE INDEX idx_logs_jid_id_kind ON logs (jid_id, kind);
'''
)
diff --git a/src/common/config.py b/src/common/config.py
index 7527528f3..960b39516 100644
--- a/src/common/config.py
+++ b/src/common/config.py
@@ -94,7 +94,7 @@ class Config:
'show_ascii_formatting_chars': [ opt_bool, True , _('If True, do not '
'remove */_ . So *abc* will be bold but with * * not removed.')],
'rst_formatting_outgoing_messages': [ opt_bool, False,
- _('Uses ReStructured text markup for HTML, plus ascii formatting if selected.')],
+ _('Uses ReStructured text markup for HTML, plus ascii formatting if selected. (If you want to use this, install docutils)')],
'sounds_on': [ opt_bool, True ],
# 'aplay', 'play', 'esdplay', 'artsplay' detected first time only
'soundplayer': [ opt_str, '' ],
@@ -143,7 +143,7 @@ class Config:
'send_on_ctrl_enter': [opt_bool, False, _('Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ Client default behaviour).')],
'show_roster_on_startup': [opt_bool, True],
'key_up_lines': [opt_int, 25, _('How many lines to store for Ctrl+KeyUP.')],
- 'version': [ opt_str, '0.10.1.3' ], # which version created the config
+ 'version': [ opt_str, '0.10.1.5' ], # which version created the config
'search_engine': [opt_str, 'http://www.google.com/search?&q=%s&sourceid=gajim'],
'dictionary_url': [opt_str, 'WIKTIONARY', _("Either custom url with %s in it where %s is the word/phrase or 'WIKTIONARY' which means use wiktionary.")],
'always_english_wikipedia': [opt_bool, False],
diff --git a/src/common/connection.py b/src/common/connection.py
index d59a0add0..72b2767ae 100644
--- a/src/common/connection.py
+++ b/src/common/connection.py
@@ -38,11 +38,12 @@ import common.xmpp
from common import helpers
from common import gajim
from common import GnuPG
+from common import passwords
from connection_handlers import *
USE_GPG = GnuPG.USE_GPG
-from rst_xhtml_generator import create_xhtml
+from common.rst_xhtml_generator import create_xhtml
class Connection(ConnectionHandlers):
'''Connection class'''
@@ -69,7 +70,7 @@ class Connection(ConnectionHandlers):
self.last_io = gajim.idlequeue.current_time()
self.last_sent = []
self.last_history_line = {}
- self.password = gajim.config.get_per('accounts', name, 'password')
+ self.password = passwords.get_password(name)
self.server_resource = gajim.config.get_per('accounts', name, 'resource')
if gajim.config.get_per('accounts', self.name, 'keep_alives_enabled'):
self.keepalives = gajim.config.get_per('accounts', self.name,'keep_alive_every_foo_secs')
@@ -687,7 +688,7 @@ class Connection(ConnectionHandlers):
user_nick = None, xhtml = None):
if not self.connection:
return
- if not xhtml and gajim.config.get('rst_formatting_outgoing_messages'):
+ if msg and not xhtml and gajim.config.get('rst_formatting_outgoing_messages'):
xhtml = create_xhtml(msg)
if not msg and chatstate is None:
return
@@ -977,14 +978,15 @@ class Connection(ConnectionHandlers):
p = self.add_sha(p, ptype != 'unavailable')
self.connection.send(p)
- def join_gc(self, nick, room, server, password):
+ def join_gc(self, nick, room_jid, password):
+ # FIXME: This room JID needs to be normalized; see #1364
if not self.connection:
return
show = helpers.get_xmpp_show(STATUS_LIST[self.connected])
if show == 'invisible':
# Never join a room when invisible
return
- p = common.xmpp.Presence(to = '%s@%s/%s' % (room, server, nick),
+ p = common.xmpp.Presence(to = '%s/%s' % (room_jid, nick),
show = show, status = self.status)
if gajim.config.get('send_sha_in_gc_presence'):
p = self.add_sha(p)
@@ -993,12 +995,11 @@ class Connection(ConnectionHandlers):
t.setTagData('password', password)
self.connection.send(p)
#last date/time in history to avoid duplicate
- # FIXME: This JID needs to be normalized; see #1364
- jid='%s@%s' % (room, server)
- last_log = gajim.logger.get_last_date_that_has_logs(jid, is_room = True)
+ last_log = gajim.logger.get_last_date_that_has_logs(room_jid,
+ is_room = True)
if last_log is None:
last_log = 0
- self.last_history_line[jid]= last_log
+ self.last_history_line[room_jid]= last_log
def send_gc_message(self, jid, msg, xhtml = None):
if not self.connection:
diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py
index 3e955b35a..326b8d478 100644
--- a/src/common/connection_handlers.py
+++ b/src/common/connection_handlers.py
@@ -712,6 +712,7 @@ class ConnectionDisco:
q.addChild('feature', attrs = {'var': common.xmpp.NS_SI})
q.addChild('feature', attrs = {'var': common.xmpp.NS_FILE})
q.addChild('feature', attrs = {'var': common.xmpp.NS_MUC})
+ q.addChild('feature', attrs = {'var': common.xmpp.NS_XHTML_IM})
self.connection.send(iq)
raise common.xmpp.NodeProcessed
@@ -819,6 +820,8 @@ class ConnectionVcard:
puny_jid = helpers.sanitize_filename(jid)
path = os.path.join(gajim.VCARD_PATH, puny_jid)
if jid in self.room_jids or os.path.isdir(path):
+ if not nick:
+ return
# remove room_jid file if needed
if os.path.isfile(path):
os.remove(path)
diff --git a/src/common/exceptions.py b/src/common/exceptions.py
index 4731829f5..bceef79a4 100644
--- a/src/common/exceptions.py
+++ b/src/common/exceptions.py
@@ -1,11 +1,7 @@
## exceptions.py
##
-## Contributors for this file:
-## - Yann Le Boulanger
-## -
-##
## Copyright (C) 2005-2006 Yann Le Boulanger
-## Nikos Kouremenos
+## Copyright (C) 2005-2006 Nikos Kouremenos
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
@@ -48,3 +44,12 @@ class SessionBusNotPresent(Exception):
def __str__(self):
return _('Session bus is not available.\nTry reading http://trac.gajim.org/wiki/GajimDBus')
+
+class GajimGeneralException(Exception):
+ '''This exception ir our general exception'''
+ def __init__(self, text=''):
+ Exception.__init__(self)
+ self.text = text
+
+ def __str__(self):
+ return self.text
diff --git a/src/common/gajim.py b/src/common/gajim.py
index 03c04ac45..e353f284c 100644
--- a/src/common/gajim.py
+++ b/src/common/gajim.py
@@ -139,10 +139,10 @@ def get_nick_from_fjid(jid):
# gaim@conference.jabber.no/nick/nick-continued
return jid.split('/', 1)[1]
-def get_room_name_and_server_from_room_jid(jid):
- room_name = get_nick_from_jid(jid)
+def get_name_and_server_from_jid(jid):
+ name = get_nick_from_jid(jid)
server = get_server_from_jid(jid)
- return room_name, server
+ return name, server
def get_room_and_nick_from_fjid(jid):
# fake jid is the jid for a contact in a room
@@ -335,7 +335,8 @@ def get_priority(account, show):
'''return the priority an account must have'''
if not show:
show = 'online'
- if show in priority_dict and config.get_per('accounts', account,
- 'adjust_priority_with_status'):
- return priority_dict[show]
+
+ if show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible') and \
+ config.get_per('accounts', account, 'adjust_priority_with_status'):
+ return config.get_per('accounts', account, 'autopriority_' + show)
return config.get_per('accounts', account, 'priority')
diff --git a/src/common/helpers.py b/src/common/helpers.py
index 96a1b790e..c482427b7 100644
--- a/src/common/helpers.py
+++ b/src/common/helpers.py
@@ -28,8 +28,10 @@ from encodings.punycode import punycode_encode
import gajim
from i18n import Q_
+from i18n import ngettext
from xmpp_stringprep import nodeprep, resourceprep, nameprep
+
try:
import winsound # windows-only built-in module for playing wav
import win32api
@@ -814,3 +816,110 @@ def get_chat_control(account, contact):
highest_contact.resource:
return None
return gajim.interface.msg_win_mgr.get_control(contact.jid, account)
+
+def reduce_chars_newlines(text, max_chars = 0, max_lines = 0):
+ '''Cut the chars after 'max_chars' on each line
+ and show only the first 'max_lines'.
+ If any of the params is not present (None or 0) the action
+ on it is not performed'''
+
+ def _cut_if_long(string):
+ if len(string) > max_chars:
+ string = string[:max_chars - 3] + '...'
+ return string
+
+ if isinstance(text, str):
+ text = text.decode('utf-8')
+
+ if max_lines == 0:
+ lines = text.split('\n')
+ else:
+ lines = text.split('\n', max_lines)[:max_lines]
+ if max_chars > 0:
+ if lines:
+ lines = map(lambda e: _cut_if_long(e), lines)
+ if lines:
+ reduced_text = reduce(lambda e, e1: e + '\n' + e1, lines)
+ else:
+ reduced_text = ''
+ return reduced_text
+
+def get_notification_icon_tooltip_text():
+ text = None
+ unread_chat = gajim.events.get_nb_events(types = ['printed_chat',
+ 'chat'])
+ unread_single_chat = gajim.events.get_nb_events(types = ['normal'])
+ unread_gc = gajim.events.get_nb_events(types = ['printed_gc_msg',
+ 'gc_msg'])
+ unread_pm = gajim.events.get_nb_events(types = ['printed_pm', 'pm'])
+
+ accounts = get_accounts_info()
+
+ if unread_chat or unread_single_chat or unread_gc or unread_pm:
+ text = 'Gajim '
+ awaiting_events = unread_chat + unread_single_chat + unread_gc + unread_pm
+ if awaiting_events == unread_chat or awaiting_events == unread_single_chat \
+ or awaiting_events == unread_gc or awaiting_events == unread_pm:
+ # This condition is like previous if but with xor...
+ # Print in one line
+ text += '-'
+ else:
+ # Print in multiple lines
+ text += '\n '
+ if unread_chat:
+ text += ngettext(
+ ' %d unread message',
+ ' %d unread messages',
+ unread_chat, unread_chat, unread_chat)
+ text += '\n '
+ if unread_single_chat:
+ text += ngettext(
+ ' %d unread single message',
+ ' %d unread single messages',
+ unread_single_chat, unread_single_chat, unread_single_chat)
+ text += '\n '
+ if unread_gc:
+ text += ngettext(
+ ' %d unread group chat message',
+ ' %d unread group chat messages',
+ unread_gc, unread_gc, unread_gc)
+ text += '\n '
+ if unread_pm:
+ text += ngettext(
+ ' %d unread private message',
+ ' %d unread private messages',
+ unread_pm, unread_pm, unread_pm)
+ text += '\n '
+ text = text[:-4] # remove latest '\n '
+ elif len(accounts) > 1:
+ text = _('Gajim')
+ elif len(accounts) == 1:
+ message = accounts[0]['status_line']
+ message = reduce_chars_newlines(message, 100, 1)
+ text = _('Gajim - %s') % message
+ else:
+ text = _('Gajim - %s') % get_uf_show('offline')
+
+ return text
+
+def get_accounts_info():
+ '''helper for notification icon tooltip'''
+ accounts = []
+ accounts_list = gajim.contacts.get_accounts()
+ accounts_list.sort()
+ for account in accounts_list:
+ status_idx = gajim.connections[account].connected
+ # uncomment the following to hide offline accounts
+ # if status_idx == 0: continue
+ status = gajim.SHOW_LIST[status_idx]
+ message = gajim.connections[account].status
+ single_line = get_uf_show(status)
+ if message is None:
+ message = ''
+ else:
+ message = message.strip()
+ if message != '':
+ single_line += ': ' + message
+ accounts.append({'name': account, 'status_line': single_line,
+ 'show': status, 'message': message})
+ return accounts
diff --git a/src/common/logger.py b/src/common/logger.py
index dfc06941d..5a3343f18 100644
--- a/src/common/logger.py
+++ b/src/common/logger.py
@@ -1,17 +1,7 @@
## logger.py
##
-## Contributors for this file:
-## - Yann Le Boulanger
-## - Nikos Kouremenos
-##
-## Copyright (C) 2003-2004 Yann Le Boulanger
-## Vincent Hanquez
-## Copyright (C) 2005 Yann Le Boulanger
-## Vincent Hanquez
-## Nikos Kouremenos
-## Dimitur Kirov
-## Travis Shirk
-## Norman Rasmussen
+## Copyright (C) 2005-2006 Nikos Kouremenos
+## Copyright (C) 2005-2006 Yann Le Boulanger
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
@@ -136,9 +126,11 @@ class Logger:
and after that all okay'''
possible_room_jid, possible_nick = jid.split('/', 1)
+ return self.jid_is_room_jid(possible_room_jid)
+ def jid_is_room_jid(self, jid):
self.cur.execute('SELECT jid_id FROM jids WHERE jid=? AND type=?',
- (possible_room_jid, constants.JID_ROOM_TYPE))
+ (jid, constants.JID_ROOM_TYPE))
row = self.cur.fetchone()
if row is None:
return False
diff --git a/src/common/optparser.py b/src/common/optparser.py
index 69e736c0a..596e99d0b 100644
--- a/src/common/optparser.py
+++ b/src/common/optparser.py
@@ -126,8 +126,7 @@ class OptionsParser:
os.chmod(self.__filename, 0600)
def update_config(self, old_version, new_version):
- # Convert '0.x.y' to (0, x, y)
- old_version_list = old_version.split('.')
+ old_version_list = old_version.split('.') # convert '0.x.y' to (0, x, y)
old = []
while len(old_version_list):
old.append(int(old_version_list.pop(0)))
@@ -146,7 +145,11 @@ class OptionsParser:
self.update_config_to_01012()
if old < [0, 10, 1, 3] and new >= [0, 10, 1, 3]:
self.update_config_to_01013()
-
+ if old < [0, 10, 1, 4] and new >= [0, 10, 1, 4]:
+ self.update_config_to_01014()
+ if old < [0, 10, 1, 5] and new >= [0, 10, 1, 5]:
+ self.update_config_to_01015()
+
gajim.logger.init_vars()
gajim.config.set('version', new_version)
@@ -301,3 +304,46 @@ class OptionsParser:
pass
con.close()
gajim.config.set('version', '0.10.1.3')
+
+ def update_config_to_01014(self):
+ '''apply indeces to the logs database'''
+ import exceptions
+ try:
+ from pysqlite2 import dbapi2 as sqlite
+ except ImportError:
+ raise exceptions.PysqliteNotAvailable
+ import logger
+ print _('migrating logs database to indeces')
+ con = sqlite.connect(logger.LOG_DB_PATH)
+ cur = con.cursor()
+ # apply indeces
+ try:
+ cur.executescript(
+ '''
+ CREATE INDEX idx_logs_jid_id_kind ON logs (jid_id, kind);
+ CREATE INDEX idx_unread_messages_jid_id ON unread_messages (jid_id);
+ '''
+ )
+
+ con.commit()
+ except:
+ pass
+ con.close()
+ gajim.config.set('version', '0.10.1.4')
+
+ def update_config_to_01015(self):
+ '''clean show values in logs database'''
+ from pysqlite2 import dbapi2 as sqlite
+ import logger
+ con = sqlite.connect(logger.LOG_DB_PATH)
+ cur = con.cursor()
+ status = dict((i[5:].lower(), logger.constants.__dict__[i]) for i in \
+ logger.constants.__dict__.keys() if i.startswith('SHOW_'))
+ for show in status:
+ cur.execute('update logs set show = ? where show = ?;', (status[show],
+ show))
+ cur.execute('update logs set show = NULL where show not in (0, 1, 2, 3, 4, 5);')
+ con.commit()
+ cur.close()
+ con.close()
+ gajim.config.set('version', '0.10.1.5')
diff --git a/src/common/passwords.py b/src/common/passwords.py
new file mode 100644
index 000000000..3c7b7237c
--- /dev/null
+++ b/src/common/passwords.py
@@ -0,0 +1,85 @@
+##
+## Copyright (C) 2006 Gustavo J. A. M. Carneiro
+## Copyright (C) 2006 Nikos Kouremenos
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published
+## by the Free Software Foundation; version 2 only.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+
+__all__ = ['get_password', 'save_password']
+
+import gobject
+
+from common import gajim
+
+try:
+ import gnomekeyring
+except ImportError:
+ USER_HAS_GNOMEKEYRING = False
+else:
+ USER_HAS_GNOMEKEYRING = True
+
+
+class SimplePasswordStorage(object):
+ def get_password(self, account_name):
+ return gajim.config.get_per('accounts', account_name, 'password')
+
+ def save_password(self, account_name, password):
+ gajim.connections[account_name].password = password
+
+
+class GnomePasswordStorage(object):
+ def __init__(self):
+ self.keyring = gnomekeyring.get_default_keyring_sync()
+
+ def get_password(self, account_name):
+ conf = gajim.config.get_per('accounts', account_name, 'password')
+ if conf is None:
+ return None
+ try:
+ unused, auth_token = conf.split('gnomekeyring:')
+ auth_token = int(auth_token)
+ except ValueError:
+ password = conf
+ ## migrate the password over to keyring
+ self.save_password(account_name, password, update=False)
+ return password
+ try:
+ return gnomekeyring.item_get_info_sync(self.keyring,
+ auth_token).get_secret()
+ except gnomekeyring.DeniedError:
+ return None
+
+ def save_password(self, account_name, password, update=True):
+ display_name = _('Gajim account %s') % account_name
+ attributes = dict(account_name=str(account_name), gajim=1)
+ auth_token = gnomekeyring.item_create_sync(
+ self.keyring, gnomekeyring.ITEM_GENERIC_SECRET,
+ display_name, attributes, password, update)
+ token = 'gnomekeyring:%i' % auth_token
+ gajim.config.set_per('accounts', account_name, 'password', token)
+
+
+storage = None
+def get_storage():
+ global storage
+ if storage is None: # None is only in first time get_storage is called
+ if USER_HAS_GNOMEKEYRING:
+ #FIXME: detect if we're running under GNOME or not
+ #before deciding to use the GnomeKeyring backend
+ storage = GnomePasswordStorage()
+ else:
+ storage = SimplePasswordStorage()
+ return storage
+
+def get_password(account_name):
+ return get_storage().get_password(account_name)
+
+def save_password(account_name, password):
+ return get_storage().save_password(account_name, password)
diff --git a/src/common/rst_xhtml_generator.py b/src/common/rst_xhtml_generator.py
new file mode 100644
index 000000000..c69771506
--- /dev/null
+++ b/src/common/rst_xhtml_generator.py
@@ -0,0 +1,126 @@
+## rst_xhtml_generator.py
+##
+## Copyright (C) 2006 Yann Le Boulanger
+## Copyright (C) 2006 Nikos Kouremenos
+## Copyright (C) 2006 Santiago Gala
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published
+## by the Free Software Foundation; version 2 only.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+
+try:
+ from docutils import io
+ from docutils.core import Publisher
+ from docutils.parsers.rst import roles
+ from docutils import nodes,utils
+ from docutils.parsers.rst.roles import set_classes
+except:
+ def create_xhtml(text):
+ return None
+else:
+ def jep_reference_role(role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ '''Role to make handy references to Jabber Enhancement Proposals (JEP).
+
+ Use as :JEP:`71` (or jep, or jep-reference).
+ Modeled after the sample in docutils documentation.
+ '''
+
+ jep_base_url = 'http://www.jabber.org/jeps/'
+ jep_url = 'jep-%04d.html'
+ try:
+ jepnum = int(text)
+ if jepnum <= 0:
+ raise ValueError
+ except ValueError:
+ msg = inliner.reporter.error(
+ 'JEP number must be a number greater than or equal to 1; '
+ '"%s" is invalid.' % text, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ ref = jep_base_url + jep_url % jepnum
+ set_classes(options)
+ node = nodes.reference(rawtext, 'JEP ' + utils.unescape(text), refuri=ref,
+ **options)
+ return [node], []
+
+ roles.register_canonical_role('jep-reference', jep_reference_role)
+ from docutils.parsers.rst.languages.en import roles
+ roles['jep-reference'] = 'jep-reference'
+ roles['jep'] = 'jep-reference'
+
+ class HTMLGenerator:
+ '''Really simple HTMLGenerator starting from publish_parts.
+
+ It reuses the docutils.core.Publisher class, which means it is *not*
+ threadsafe.
+ '''
+ def __init__(self,
+ settings_spec=None,
+ settings_overrides=dict(report_level=5, halt_level=5),
+ config_section='general'):
+ self.pub = Publisher(reader=None, parser=None, writer=None,
+ settings=None,
+ source_class=io.StringInput,
+ destination_class=io.StringOutput)
+ self.pub.set_components(reader_name='standalone',
+ parser_name='restructuredtext',
+ writer_name='html')
+ # hack: JEP-0071 does not allow HTML char entities, so we hack our way
+ # out of it.
+ # — == u"\u2014"
+ # a setting to only emit charater entities in the writer would be nice
+ # FIXME: several are emitted, and they are explicitly forbidden
+ # in the JEP
+ # == u"\u00a0"
+ self.pub.writer.translator_class.attribution_formats['dash'] = (
+ u'\u2014', '')
+ self.pub.process_programmatic_settings(settings_spec,
+ settings_overrides,
+ config_section)
+
+
+ def create_xhtml(self, text,
+ destination=None,
+ destination_path=None,
+ enable_exit_status=None):
+ ''' Create xhtml for a fragment of IM dialog.
+ We can use the source_name to store info about
+ the message.'''
+ self.pub.set_source(text, None)
+ self.pub.set_destination(destination, destination_path)
+ output = self.pub.publish(enable_exit_status=enable_exit_status)
+ # kludge until we can get docutils to stop generating (rare)
+ # entities
+ return u'\u00a0'.join(self.pub.writer.parts['fragment'].strip().split(
+ ' '))
+
+ Generator = HTMLGenerator()
+
+ def create_xhtml(text):
+ return Generator.create_xhtml(text)
+
+
+if __name__ == '__main__':
+ print Generator.create_xhtml('''
+test::
+
+ >>> print 1
+ 1
+
+*I* like it. It is for :JEP:`71`
+
+this `` should trigger`` should trigger the problem.
+
+''')
+ print Generator.create_xhtml('''
+*test1
+
+test2_
+''')
diff --git a/src/config.py b/src/config.py
index 0db7eccfb..cf1676bd7 100644
--- a/src/config.py
+++ b/src/config.py
@@ -38,8 +38,11 @@ except:
from common import helpers
from common import gajim
from common import connection
+from common import passwords
from common import zeroconf
+from common.exceptions import GajimGeneralException as GajimGeneralException
+
#---------- PreferencesWindow class -------------#
class PreferencesWindow:
'''Class for Preferences window'''
@@ -435,8 +438,7 @@ class PreferencesWindow:
self.xml.get_widget('custom_apps_frame').set_no_show_all(True)
if gajim.config.get('autodetect_browser_mailer'):
self.applications_combobox.set_active(0)
- gtkgui_helpers.autodetect_browser_mailer()
- # autodetect_browser_mailer is now False.
+ # else autodetect_browser_mailer is False.
# so user has 'Always Use GNOME/KDE' or Custom
elif gajim.config.get('openwith') == 'gnome-open':
self.applications_combobox.set_active(1)
@@ -1324,6 +1326,8 @@ class AccountModificationWindow:
config['password'] = self.xml.get_widget('password_entry').get_text().\
decode('utf-8')
config['resource'] = resource
+ config['adjust_priority_with_status'] = self.xml.get_widget(
+ 'adjust_priority_with_status_checkbutton').get_active()
config['priority'] = self.xml.get_widget('priority_spinbutton').\
get_value_as_int()
config['autoconnect'] = self.xml.get_widget('autoconnect_checkbutton').\
@@ -1442,27 +1446,28 @@ class AccountModificationWindow:
# check if relogin is needed
relogin_needed = False
if self.options_changed_need_relogin(config,
- ('resource', 'proxy', 'usessl', 'keyname',
- 'use_custom_host', 'custom_host')):
+ ('resource', 'proxy', 'usessl', 'keyname',
+ 'use_custom_host', 'custom_host')):
relogin_needed = True
elif config['use_custom_host'] and (self.option_changed(config,
- 'custom_host') or self.option_changed(config, 'custom_port')):
+ 'custom_host') or self.option_changed(config, 'custom_port')):
relogin_needed = True
if self.option_changed(config, 'use_ft_proxies') and \
config['use_ft_proxies']:
gajim.connections[self.account].discover_ft_proxies()
- if self.option_changed(config, 'priority'):
+ if self.option_changed(config, 'priority') or self.option_changed(
+ config, 'adjust_priority_with_status'):
resend_presence = True
for opt in config:
gajim.config.set_per('accounts', name, opt, config[opt])
if config['savepass']:
- gajim.connections[name].password = config['password']
+ passwords.save_password(name, config['password'])
else:
- gajim.connections[name].password = None
+ passwords.save_password(name, None)
# refresh accounts window
if gajim.interface.instances.has_key('accounts'):
gajim.interface.instances['accounts'].init_accounts()
@@ -1511,7 +1516,7 @@ class AccountModificationWindow:
def on_change_password_button_clicked(self, widget):
try:
dialog = dialogs.ChangePasswordDialog(self.account)
- except RuntimeError:
+ except GajimGeneralException:
#if we showed ErrorDialog, there will not be dialog instance
return
@@ -2497,10 +2502,10 @@ class ManageBookmarksWindow:
self.window = self.xml.get_widget('manage_bookmarks_window')
self.window.set_transient_for(gajim.interface.roster.window)
- #Account-JID, RoomName, Room-JID, Autojoin, Passowrd, Nick, Show_Status
+ # Account-JID, RoomName, Room-JID, Autojoin, Passowrd, Nick, Show_Status
self.treestore = gtk.TreeStore(str, str, str, bool, str, str, str)
- #Store bookmarks in treeview.
+ # Store bookmarks in treeview.
for account in gajim.connections:
if gajim.connections[account].connected <= 1:
continue
@@ -2605,7 +2610,7 @@ class ManageBookmarksWindow:
account = model[add_to][1].decode('utf-8')
nick = gajim.nicks[account]
- self.treestore.append(add_to, [account, _('New Room'), '', False, '',
+ self.treestore.append(add_to, [account, _('New Group Chat'), '', False, '',
nick, 'in_and_out'])
self.view.expand_row(model.get_path(add_to), True)
@@ -2943,7 +2948,7 @@ class AccountCreationWizardWindow:
self.account = server + str(i)
i += 1
- username, server = gajim.get_room_name_and_server_from_room_jid(jid)
+ username, server = gajim.get_name_and_server_from_jid(jid)
self.save_account(username, server, savepass, password)
self.cancel_button.hide()
self.back_button.hide()
diff --git a/src/conversation_textview.py b/src/conversation_textview.py
index 18e907a6f..ae0f1474e 100644
--- a/src/conversation_textview.py
+++ b/src/conversation_textview.py
@@ -1,17 +1,8 @@
## conversation_textview.py
##
-## Contributors for this file:
-## - Yann Le Boulanger
-## - Nikos Kouremenos
-##
-## Copyright (C) 2003-2004 Yann Le Boulanger
-## Vincent Hanquez
-## Copyright (C) 2005 Yann Le Boulanger
-## Vincent Hanquez
-## Nikos Kouremenos
-## Dimitur Kirov
-## Travis Shirk
-## Norman Rasmussen
+## Copyright (C) 2005-2006 Yann Le Boulanger
+## Copyright (C) 2005-2006 Nikos Kouremenos
+## Copyright (C) 2005-2006 Travis Shirk
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
@@ -40,13 +31,17 @@ from calendar import timegm
from common.fuzzyclock import FuzzyClock
from htmltextview import HtmlTextView
-
+from common.exceptions import GajimGeneralException as GajimGeneralException
class ConversationTextview:
'''Class for the conversation textview (where user reads already said messages)
for chat/groupchat windows'''
- def __init__(self, account):
- # no need to inherit TextView, use it as property is safer
+ def __init__(self, account, used_in_history_window = False):
+ '''if used_in_history_window is True, then we do not show
+ Clear menuitem in context menu'''
+ self.used_in_history_window = used_in_history_window
+
+ # no need to inherit TextView, use it as atrribute is safer
self.tv = HtmlTextView()
self.tv.html_hyperlink_handler = self.html_hyperlink_handler
@@ -61,11 +56,13 @@ class ConversationTextview:
self.handlers = {}
# connect signals
- id = self.tv.connect('motion_notify_event', self.on_textview_motion_notify_event)
+ id = self.tv.connect('motion_notify_event',
+ self.on_textview_motion_notify_event)
self.handlers[id] = self.tv
id = self.tv.connect('populate_popup', self.on_textview_populate_popup)
self.handlers[id] = self.tv
- id = self.tv.connect('button_press_event', self.on_textview_button_press_event)
+ id = self.tv.connect('button_press_event',
+ self.on_textview_button_press_event)
self.handlers[id] = self.tv
self.account = account
@@ -154,7 +151,7 @@ class ConversationTextview:
self.handlers[i].disconnect(i)
del self.handlers
self.tv.destroy()
- #TODO
+ #FIXME:
# self.line_tooltip.destroy()
def update_tags(self):
@@ -320,19 +317,29 @@ class ConversationTextview:
def on_textview_populate_popup(self, textview, menu):
'''we override the default context menu and we prepend Clear
+ (only if used_in_history_window is False)
and if we have sth selected we show a submenu with actions on the phrase
(see on_conversation_textview_button_press_event)'''
- item = gtk.SeparatorMenuItem()
- menu.prepend(item)
- item = gtk.ImageMenuItem(gtk.STOCK_CLEAR)
- menu.prepend(item)
- id = item.connect('activate', self.clear)
- self.handlers[id] = item
+
+ separator_menuitem_was_added = False
+ if not self.used_in_history_window:
+ item = gtk.SeparatorMenuItem()
+ menu.prepend(item)
+ separator_menuitem_was_added = True
+
+ item = gtk.ImageMenuItem(gtk.STOCK_CLEAR)
+ menu.prepend(item)
+ id = item.connect('activate', self.clear)
+ self.handlers[id] = item
+
if self.selected_phrase:
- s = self.selected_phrase
- if len(s) > 25:
- s = s[:21] + '...'
- item = gtk.MenuItem(_('Actions for "%s"') % s)
+ if not separator_menuitem_was_added:
+ item = gtk.SeparatorMenuItem()
+ menu.prepend(item)
+
+ self.selected_phrase = helpers.reduce_chars_newlines(
+ self.selected_phrase, 25)
+ item = gtk.MenuItem(_('_Actions for "%s"') % self.selected_phrase)
menu.prepend(item)
submenu = gtk.Menu()
item.set_submenu(submenu)
@@ -369,7 +376,8 @@ class ConversationTextview:
item.set_property('sensitive', False)
else:
link = dict_link % self.selected_phrase
- id = item.connect('activate', self.visit_url_from_menuitem, link)
+ id = item.connect('activate', self.visit_url_from_menuitem,
+ link)
self.handlers[id] = item
submenu.append(item)
@@ -385,13 +393,17 @@ class ConversationTextview:
id = item.connect('activate', self.visit_url_from_menuitem, link)
self.handlers[id] = item
submenu.append(item)
+
+ item = gtk.MenuItem(_('Open as _Link'))
+ id = item.connect('activate', self.visit_url_from_menuitem, link)
+ self.handlers[id] = item
+ submenu.append(item)
menu.show_all()
def on_textview_button_press_event(self, widget, event):
# If we clicked on a taged text do NOT open the standard popup menu
# if normal text check if we have sth selected
-
self.selected_phrase = ''
if event.button != 3: # if not right click
@@ -430,18 +442,16 @@ class ConversationTextview:
def on_start_chat_activate(self, widget, jid):
gajim.interface.roster.new_chat_from_jid(self.account, jid)
- def on_join_group_chat_menuitem_activate(self, widget, jid):
- room, server = jid.split('@')
- if gajim.interface.instances[self.account].has_key('join_gc'):
+ def on_join_group_chat_menuitem_activate(self, widget, room_jid):
+ if 'join_gc' in gajim.interface.instances[self.account]:
instance = gajim.interface.instances[self.account]['join_gc']
- instance.xml.get_widget('server_entry').set_text(server)
- instance.xml.get_widget('room_entry').set_text(room)
+ instance.xml.get_widget('room_jid_entry').set_text(room_jid)
gajim.interface.instances[self.account]['join_gc'].window.present()
else:
try:
gajim.interface.instances[self.account]['join_gc'] = \
- dialogs.JoinGroupchatWindow(self.account, server, room)
- except RuntimeError:
+ dialogs.JoinGroupchatWindow(self.account, room_jid)
+ except GajimGeneralException:
pass
def on_add_to_roster_activate(self, widget, jid):
@@ -463,6 +473,7 @@ class ConversationTextview:
childs[6].hide() # join group chat
childs[7].hide() # add to roster
else: # It's a mail or a JID
+ text = text.lower()
id = childs[2].connect('activate', self.on_copy_link_activate, text)
self.handlers[id] = childs[2]
id = childs[3].connect('activate', self.on_open_link_activate, kind, text)
@@ -701,7 +712,6 @@ class ConversationTextview:
# if tim_format comes as unicode because of day_str.
# we convert it to the encoding that we want (and that is utf-8)
tim_format = helpers.ensure_utf8_string(tim_format)
- tim_format = tim_format.encode('utf-8')
buffer.insert_with_tags_by_name(end_iter, tim_format + ' ',
*other_tags_for_time)
elif current_print_time == 'sometimes' and kind != 'info':
diff --git a/src/dialogs.py b/src/dialogs.py
index b5f919454..eae459362 100644
--- a/src/dialogs.py
+++ b/src/dialogs.py
@@ -40,6 +40,7 @@ from advanced import AdvancedConfigurationWindow
from common import gajim
from common import helpers
+from common.exceptions import GajimGeneralException as GajimGeneralException
class EditGroupsDialog:
'''Class for the edit group dialog window'''
@@ -139,6 +140,9 @@ class EditGroupsDialog:
group = self.xml.get_widget('group_entry').get_text().decode('utf-8')
if not group:
return
+ # Do not allow special groups
+ if group in helpers.special_groups:
+ return
# check if it already exists
model = self.list.get_model()
iter = model.get_iter_root()
@@ -180,14 +184,16 @@ class EditGroupsDialog:
if account not in accounts:
accounts.append(account)
for g in gajim.groups[account].keys():
- if g in helpers.special_groups:
- continue
if g in groups:
continue
groups[g] = 0
for g in contact.groups:
groups[g] += 1
- group_list = groups.keys()
+ group_list = []
+ # Remove special groups if they are empty
+ for group in groups:
+ if group not in helpers.special_groups or groups[group] > 0:
+ group_list.append(group)
group_list.sort()
for group in group_list:
iter = store.append()
@@ -506,7 +512,7 @@ _('Please fill in the data of the contact you want to add in account %s') %accou
if type_ == 'jabber':
self.uid_entry.set_text(jid)
else:
- uid, transport = gajim.get_room_name_and_server_from_room_jid(jid)
+ uid, transport = gajim.get_name_and_server_from_jid(jid)
self.uid_entry.set_text(uid.replace('%', '@', 1))
#set protocol_combobox
model = self.protocol_combobox.get_model()
@@ -1076,32 +1082,33 @@ class SubscriptionRequestWindow:
class JoinGroupchatWindow:
- def __init__(self, account, server = '', room = '', nick = '',
- automatic = False):
+ def __init__(self, account, room_jid = '', nick = '', automatic = False):
'''automatic is a dict like {'invities': []}
If automatic is not empty, this means room must be automaticaly configured
and when done, invities must be automatically invited'''
- if server and room:
- jid = room + '@' + server
- if jid in gajim.gc_connected[account] and gajim.gc_connected[account][jid]:
- ErrorDialog(_('You are already in room %s') % jid)
- raise RuntimeError, 'You are already in this room'
+ if room_jid != '':
+ if room_jid in gajim.gc_connected[account] and\
+ gajim.gc_connected[account][room_jid]:
+ ErrorDialog(_('You are already in room %s') % room_jid)
+ raise GajimGeneralException, 'You are already in this room'
self.account = account
self.automatic = automatic
if nick == '':
nick = gajim.nicks[self.account]
if gajim.connections[account].connected < 2:
ErrorDialog(_('You are not connected to the server'),
-_('You can not join a group chat unless you are connected.'))
- raise RuntimeError, 'You must be connected to join a groupchat'
+ _('You can not join a group chat unless you are connected.'))
+ raise GajimGeneralException, 'You must be connected to join a groupchat'
self._empty_required_widgets = []
self.xml = gtkgui_helpers.get_glade('join_groupchat_window.glade')
self.window = self.xml.get_widget('join_groupchat_window')
- self.xml.get_widget('server_entry').set_text(server)
- self.xml.get_widget('room_entry').set_text(room)
- self.xml.get_widget('nickname_entry').set_text(nick)
+ self._room_jid_entry = self.xml.get_widget('room_jid_entry')
+ self._nickname_entry = self.xml.get_widget('nickname_entry')
+
+ self._room_jid_entry.set_text(room_jid)
+ self._nickname_entry.set_text(nick)
self.xml.signal_autoconnect(self)
gajim.interface.instances[account]['join_gc'] = self #now add us to open windows
if len(gajim.connections) > 1:
@@ -1121,18 +1128,13 @@ _('You can not join a group chat unless you are connected.'))
self.recently_combobox.append_text(g)
if len(self.recently_groupchat) == 0:
self.recently_combobox.set_sensitive(False)
- elif server == '' and room == '':
+ elif room_jid == '':
self.recently_combobox.set_active(0)
- self.xml.get_widget('room_entry').select_region(0, -1)
- elif room and server:
+ self._room_jid_entry.select_region(0, -1)
+ elif room_jid != '':
self.xml.get_widget('join_button').grab_focus()
- self._server_entry = self.xml.get_widget('server_entry')
- self._room_entry = self.xml.get_widget('room_entry')
- self._nickname_entry = self.xml.get_widget('nickname_entry')
- if not self._server_entry.get_text():
- self._empty_required_widgets.append(self._server_entry)
- if not self._room_entry.get_text():
+ if not self._room_jid_entry.get_text():
self._empty_required_widgets.append(self._room_entry)
if not self._nickname_entry.get_text():
self._empty_required_widgets.append(self._nickname_entry)
@@ -1160,27 +1162,11 @@ _('You can not join a group chat unless you are connected.'))
if len(self._empty_required_widgets) == 0:
self.xml.get_widget('join_button').set_sensitive(True)
- def on_room_entry_key_press_event(self, widget, event):
- # Check for pressed @ and jump to server_entry if found
- if event.keyval == gtk.keysyms.at:
- self.xml.get_widget('server_entry').grab_focus()
- return True
-
- def on_server_entry_key_press_event(self, widget, event):
- # If backspace is pressed in empty server_entry, return to the room entry
- backspace = event.keyval == gtk.keysyms.BackSpace
- server_entry = self.xml.get_widget('server_entry')
- empty = len(server_entry.get_text()) == 0
- if backspace and empty:
- self.xml.get_widget('room_entry').grab_focus()
- return True
-
def on_recently_combobox_changed(self, widget):
model = widget.get_model()
- iter = widget.get_active_iter()
- gid = model[iter][0].decode('utf-8')
- self.xml.get_widget('room_entry').set_text(gid.split('@')[0])
- self.xml.get_widget('server_entry').set_text(gid.split('@')[1])
+ iter_ = widget.get_active_iter()
+ room_jid = model[iter_][0].decode('utf-8')
+ self._room_jid_entry.set_text(room_jid)
def on_cancel_button_clicked(self, widget):
'''When Cancel button is clicked'''
@@ -1188,30 +1174,29 @@ _('You can not join a group chat unless you are connected.'))
def on_join_button_clicked(self, widget):
'''When Join button is clicked'''
- nickname = self.xml.get_widget('nickname_entry').get_text().decode(
- 'utf-8')
- room = self.xml.get_widget('room_entry').get_text().decode('utf-8')
- server = self.xml.get_widget('server_entry').get_text().decode('utf-8')
+ nickname = self._nickname_entry.get_text().decode('utf-8')
+ room_jid = self._room_jid_entry.get_text().decode('utf-8')
password = self.xml.get_widget('password_entry').get_text().decode(
'utf-8')
- jid = '%s@%s' % (room, server)
try:
- jid = helpers.parse_jid(jid)
+ room_jid = helpers.parse_jid(room_jid)
except:
- ErrorDialog(_('Invalid room or server name'),
- _('The room name or server name has not allowed characters.'))
+ ErrorDialog(_('Invalid room Jabber ID'),
+ _('The room Jabber ID has not allowed characters.'))
return
- if jid in self.recently_groupchat:
- self.recently_groupchat.remove(jid)
- self.recently_groupchat.insert(0, jid)
+ if room_jid in self.recently_groupchat:
+ self.recently_groupchat.remove(room_jid)
+ self.recently_groupchat.insert(0, room_jid)
if len(self.recently_groupchat) > 10:
self.recently_groupchat = self.recently_groupchat[0:10]
- gajim.config.set('recently_groupchat', ' '.join(self.recently_groupchat))
+ gajim.config.set('recently_groupchat',
+ ' '.join(self.recently_groupchat))
if self.automatic:
- gajim.automatic_rooms[self.account][jid] = self.automatic
- gajim.interface.roster.join_gc_room(self.account, jid, nickname, password)
+ gajim.automatic_rooms[self.account][room_jid] = self.automatic
+ gajim.interface.roster.join_gc_room(self.account, room_jid, nickname,
+ password)
self.window.destroy()
@@ -1271,7 +1256,7 @@ class ChangePasswordDialog:
if not account or gajim.connections[account].connected < 2:
ErrorDialog(_('You are not connected to the server'),
_('Without a connection, you can not change your password.'))
- raise RuntimeError, 'You are not connected to the server'
+ raise GajimGeneralException, 'You are not connected to the server'
self.account = account
self.xml = gtkgui_helpers.get_glade('change_password_dialog.glade')
self.dialog = self.xml.get_widget('change_password_dialog')
@@ -2189,10 +2174,9 @@ class InvitationReceivedDialog:
def on_accept_button_clicked(self, widget):
self.dialog.destroy()
- room, server = gajim.get_room_name_and_server_from_room_jid(self.room_jid)
try:
- JoinGroupchatWindow(self.account, server = server, room = room)
- except RuntimeError:
+ JoinGroupchatWindow(self.account, self.room_jid)
+ except GajimGeneralException:
pass
class ProgressDialog:
diff --git a/src/disco.py b/src/disco.py
index ff1e12c63..4dd082a5b 100644
--- a/src/disco.py
+++ b/src/disco.py
@@ -49,6 +49,7 @@ import gtkgui_helpers
from common import gajim
from common import xmpp
+from common.exceptions import GajimGeneralException as GajimGeneralException
# Dictionary mapping category, type pairs to browser class, image pairs.
# This is a function, so we can call it after the classes are declared.
@@ -121,6 +122,13 @@ class CacheDictionary:
def __call__(self):
return self.value
+ def cleanup(self):
+ for key in self.cache.keys():
+ item = self.cache[key]
+ if item.source:
+ gobject.source_remove(item.source)
+ del self.cache[key]
+
def _expire_timeout(self, key):
'''The timeout has expired, remove the object.'''
if key in self.cache:
@@ -132,8 +140,9 @@ class CacheDictionary:
item = self.cache[key]
if item.source:
gobject.source_remove(item.source)
- source = gobject.timeout_add(self.lifetime, self._expire_timeout, key)
- item.source = source
+ if self.lifetime:
+ source = gobject.timeout_add(self.lifetime, self._expire_timeout, key)
+ item.source = source
def __getitem__(self, key):
item = self.cache[key]
@@ -205,10 +214,14 @@ class ServicesCache:
ServiceCache instance.'''
def __init__(self, account):
self.account = account
- self._items = CacheDictionary(1, getrefresh = True)
- self._info = CacheDictionary(1, getrefresh = True)
+ self._items = CacheDictionary(0, getrefresh = False)
+ self._info = CacheDictionary(0, getrefresh = False)
self._cbs = {}
+ def cleanup(self):
+ self._items.cleanup()
+ self._info.cleanup()
+
def _clean_closure(self, cb, type, addr):
# A closure died, clean up
cbkey = (type, addr)
@@ -584,6 +597,7 @@ _('Without a connection, you can not browse available services'))
self.browser = None
self.window.destroy()
+ self.cache.cleanup()
for child in self.children[:]:
child.parent = None
if chain:
@@ -1178,16 +1192,10 @@ class ToplevelAgentBrowser(AgentBrowser):
if not iter:
return
service = model[iter][0].decode('utf-8')
- if service.find('@') != -1:
- services = service.split('@', 1)
- room = services[0]
- service = services[1]
- else:
- room = ''
if not gajim.interface.instances[self.account].has_key('join_gc'):
try:
- dialogs.JoinGroupchatWindow(self.account, service, room)
- except RuntimeError:
+ dialogs.JoinGroupchatWindow(self.account, service)
+ except GajimGeneralException:
pass
else:
gajim.interface.instances[self.account]['join_gc'].window.present()
@@ -1489,7 +1497,8 @@ class MucBrowser(AgentBrowser):
self.vadj = self.window.services_scrollwin.get_property('vadjustment')
self.vadj_cbid = self.vadj.connect('value-changed', self.on_scroll)
# And to size changes
- self.size_cbid = self.window.services_scrollwin.connect('size-allocate', self.on_scroll)
+ self.size_cbid = self.window.services_scrollwin.connect(
+ 'size-allocate', self.on_scroll)
def _clean_treemodel(self):
if self.size_cbid:
@@ -1518,16 +1527,12 @@ class MucBrowser(AgentBrowser):
if not iter:
return
service = model[iter][0].decode('utf-8')
- if service.find('@') != -1:
- services = service.split('@', 1)
- room = services[0]
- service = services[1]
- else:
- room = model[iter][1].decode('utf-8')
+ room = model[iter][1].decode('utf-8')
if 'join_gc' not in gajim.interface.instances[self.account]:
try:
- dialogs.JoinGroupchatWindow(self.account, service, room)
- except RuntimeError:
+ room_jid = '%s@%s' % (service, room)
+ dialogs.JoinGroupchatWindow(self.account, service)
+ except GajimGeneralException:
pass
else:
gajim.interface.instances[self.account]['join_gc'].window.present()
diff --git a/src/gajim.py b/src/gajim.py
index 611536643..e4e8693b6 100755
--- a/src/gajim.py
+++ b/src/gajim.py
@@ -4,20 +4,11 @@ exec python -OOt "$0" ${1+"$@"}
' '''
## gajim.py
##
-## Contributors for this file:
-## - Yann Le Boulanger
-## - Nikos Kouremenos
-## - Dimitur Kirov
-## - Travis Shirk
##
-## Copyright (C) 2003-2004 Yann Le Boulanger
-## Vincent Hanquez
-## Copyright (C) 2005 Yann Le Boulanger
-## Vincent Hanquez
-## Nikos Kouremenos
-## Dimitur Kirov
-## Travis Shirk
-## Norman Rasmussen
+## Copyright (C) 2003-2006 Yann Le Boulanger
+## Copyright (C) 2005-2006 Nikos Kouremenos
+## Copyright (C) 2005-2006 Dimitur Kirov
+## Copyright (C) 2005 Travis Shirk
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
@@ -82,16 +73,14 @@ except exceptions.PysqliteNotAvailable, e:
if os.name == 'nt':
try:
import winsound # windows-only built-in module for playing wav
- import win32api
- import win32con
except:
pritext = _('Gajim needs pywin32 to run')
sectext = _('Please make sure that Pywin32 is installed on your system. You can get it at %s') % 'http://sourceforge.net/project/showfiles.php?group_id=78018'
if pritext:
dlg = gtk.MessageDialog(None,
- gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
- gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, message_format = pritext)
+ gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
+ gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, message_format = pritext)
dlg.format_secondary_text(sectext)
dlg.run()
@@ -194,7 +183,6 @@ atexit.register(on_exit)
parser = optparser.OptionsParser(config_filename)
import roster_window
-import systray
import profile_window
import config
@@ -509,7 +497,8 @@ class Interface:
def handle_event_msg(self, account, array):
# 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject,
- # chatstate, msg_id, composing_jep, user_nick, xhtml)) user_nick is JEP-0172
+ # chatstate, msg_id, composing_jep, user_nick, xhtml))
+ # user_nick is JEP-0172
full_jid_with_resource = array[0]
jid = gajim.get_jid_without_resource(full_jid_with_resource)
@@ -609,7 +598,7 @@ class Interface:
msg_type, subject, resource, msg_id, array[9],
advanced_notif_num)
else:
- #xhtml in last element
+ # xhtml in last element
self.roster.on_message(jid, message, array[2], account, array[3],
msg_type, subject, resource, msg_id, array[9],
advanced_notif_num, xhtml = array[10])
@@ -1092,12 +1081,16 @@ class Interface:
if gajim.config.get('notify_on_new_gmail_email'):
img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
'new_email_recv.png')
- title = _('New E-mail on %(gmail_mail_address)s') % \
+ title = _('New mail on %(gmail_mail_address)s') % \
{'gmail_mail_address': jid}
- text = i18n.ngettext('You have %d new E-mail message', 'You have %d new E-mail messages', gmail_new_messages, gmail_new_messages, gmail_new_messages)
+ text = i18n.ngettext('You have %d new mail conversation',
+ 'You have %d new mail conversations', gmail_new_messages,
+ gmail_new_messages, gmail_new_messages)
if gajim.config.get('notify_on_new_gmail_email_extra'):
for gmessage in gmail_messages_list:
+ #FIXME: emulate Gtalk client popups. find out what they parse and how
+ #they decide what to show
# each message has a 'From', 'Subject' and 'Snippet' field
text += _('\nFrom: %(from_address)s') % \
{'from_address': gmessage['From']}
@@ -1382,12 +1375,11 @@ class Interface:
if gajim.gc_connected[account].has_key(room_jid) and\
gajim.gc_connected[account][room_jid]:
continue
- room, server = gajim.get_room_name_and_server_from_room_jid(room_jid)
nick = gc_control.nick
password = ''
if gajim.gc_passwords.has_key(room_jid):
password = gajim.gc_passwords[room_jid]
- gajim.connections[account].join_gc(nick, room, server, password)
+ gajim.connections[account].join_gc(nick, room_jid, password)
def handle_event_metacontacts(self, account, tags_list):
gajim.contacts.define_metacontacts(account, tags_list)
@@ -1946,21 +1938,18 @@ class Interface:
self.systray_enabled = False
self.systray_capabilities = False
- if os.name == 'nt':
- pass
- '''
- try:
- import systraywin32
- except: # user doesn't have trayicon capabilities
- pass
- else:
- self.systray_capabilities = True
- self.systray = systraywin32.SystrayWin32()
- '''
- else:
+ if os.name == 'nt' and gtk.pygtk_version >= (2, 10, 0) and\
+ gtk.gtk_version >= (2, 10, 0):
+ import statusicon
+ self.systray = statusicon.StatusIcon()
+ self.systray_capabilities = True
+ else: # use ours, not GTK+ one
+ # [FIXME: remove this when we migrate to 2.10 and we can do
+ # cool tooltips somehow and (not dying to keep) animation]
+ import systray
self.systray_capabilities = systray.HAS_SYSTRAY_CAPABILITIES
if self.systray_capabilities:
- self.systray = systray.Systray()
+ self.systray = systray.Systray()
if self.systray_capabilities and gajim.config.get('trayicon'):
self.show_systray()
@@ -2013,7 +2002,8 @@ if __name__ == '__main__':
cli = gnome.ui.master_client()
cli.connect('die', die_cb)
- path_to_gajim_script = gtkgui_helpers.get_abspath_for_script('gajim')
+ path_to_gajim_script = gtkgui_helpers.get_abspath_for_script(
+ 'gajim')
if path_to_gajim_script:
argv = [path_to_gajim_script]
@@ -2028,5 +2018,6 @@ if __name__ == '__main__':
gtkgui_helpers.possibly_set_gajim_as_xmpp_handler()
check_paths.check_and_possibly_create_paths()
+
Interface()
gtk.main()
diff --git a/src/groupchat_control.py b/src/groupchat_control.py
index 3590163d9..18e029a10 100644
--- a/src/groupchat_control.py
+++ b/src/groupchat_control.py
@@ -39,12 +39,13 @@ from common import helpers
from chat_control import ChatControl
from chat_control import ChatControlBase
from conversation_textview import ConversationTextview
+from common.exceptions import GajimGeneralException as GajimGeneralException
#(status_image, type, nick, shown_nick)
(
C_IMG, # image to show state (online, new message etc)
-C_TYPE, # type of the row ('contact' or 'group')
-C_NICK, # contact nickame or group name
+C_NICK, # contact nickame or ROLE name
+C_TYPE, # type of the row ('contact' or 'role')
C_TEXT, # text shown in the cellrenderer
C_AVATAR, # avatar of the contact
) = range(5)
@@ -253,7 +254,7 @@ class GroupchatControl(ChatControlBase):
id = self.list_treeview.connect('size-allocate',
self.on_treeview_size_allocate)
self.handlers[id] = self.list_treeview
- #status_image, type, nickname, shown_nick
+ #status_image, shown_nick, type, nickname, avatar
store = gtk.TreeStore(gtk.Image, str, str, str, gtk.gdk.Pixbuf)
store.set_sort_column_id(C_TEXT, gtk.SORT_ASCENDING)
self.list_treeview.set_model(store)
@@ -397,7 +398,9 @@ class GroupchatControl(ChatControlBase):
jid = self.contact.jid
num_unread = len(gajim.events.get_events(self.account, jid,
['printed_gc_msg']))
- if num_unread > 1:
+ if num_unread == 1:
+ unread = '*'
+ elif num_unread > 1:
unread = '[' + unicode(num_unread) + ']'
label_str = unread + label_str
return (label_str, color)
@@ -664,7 +667,7 @@ class GroupchatControl(ChatControlBase):
self.subject = subject
self.name_label.set_ellipsize(pango.ELLIPSIZE_END)
- subject = gtkgui_helpers.reduce_chars_newlines(subject, max_lines = 2)
+ subject = helpers.reduce_chars_newlines(subject, max_lines = 2)
subject = gtkgui_helpers.escape_for_pango_markup(subject)
font_attrs, font_attrs_small = self.get_font_attrs()
text = '%s' % (font_attrs, self.room_jid)
@@ -672,8 +675,6 @@ class GroupchatControl(ChatControlBase):
text += '\n%s' % (font_attrs_small, subject)
self.name_label.set_markup(text)
event_box = self.name_label.get_parent()
- if subject == '':
- self.subject = _('This room has no subject')
# tooltip must always hold ALL the subject
self.subject_tooltip.set_tip(event_box, self.subject)
@@ -735,7 +736,7 @@ class GroupchatControl(ChatControlBase):
if status and gajim.config.get('show_status_msgs_in_roster'):
status = status.strip()
if status != '':
- status = gtkgui_helpers.reduce_chars_newlines(status, max_lines = 1)
+ status = helpers.reduce_chars_newlines(status, max_lines = 1)
# escape markup entities and make them small italic and fg color
color = gtkgui_helpers._get_fade_color(self.list_treeview,
selected, focus)
@@ -913,9 +914,9 @@ class GroupchatControl(ChatControlBase):
role_iter = self.get_role_iter(role)
if not role_iter:
role_iter = model.append(None,
- (gajim.interface.roster.jabber_state_images['16']['closed'], 'role',
- role, '%s' % role_name, None))
- iter = model.append(role_iter, (None, 'contact', nick, name, None))
+ (gajim.interface.roster.jabber_state_images['16']['closed'], role,
+ 'role', '%s' % role_name, None))
+ iter = model.append(role_iter, (None, nick, 'contact', name, None))
if not nick in gajim.contacts.get_nick_list(self.account, self.room_jid):
gc_contact = gajim.contacts.create_gc_contact(room_jid = self.room_jid,
name = nick, show = show, status = status, role = role,
@@ -924,7 +925,7 @@ class GroupchatControl(ChatControlBase):
self.draw_contact(nick)
self.draw_avatar(nick)
# Do not ask avatar to irc rooms as irc transports reply with messages
- r, server = gajim.get_room_name_and_server_from_room_jid(self.room_jid)
+ server = gajim.get_server_from_jid(self.room_jid)
if gajim.config.get('ask_avatars_on_startup') and \
not server.startswith('irc'):
fjid = self.room_jid + '/' + nick
@@ -1038,8 +1039,10 @@ class GroupchatControl(ChatControlBase):
new_topic = message_array.pop(0)
gajim.connections[self.account].send_gc_subject(self.room_jid,
new_topic)
- else:
+ elif self.subject is not '':
self.print_conversation(self.subject, 'info')
+ else:
+ self.print_conversation(_('This room has no subject'), 'info')
self.clear(self.msg_textview)
return True
elif command == 'invite':
@@ -1067,15 +1070,13 @@ class GroupchatControl(ChatControlBase):
elif command == 'join':
# example: /join room@conference.example.com/nick
if len(message_array):
- message_array = message_array[0]
- if message_array.find('@') >= 0:
- room, servernick = message_array.split('@')
- if servernick.find('/') >= 0:
- server, nick = servernick.split('/', 1)
+ room_jid = message_array[0]
+ if room_jid.find('@') >= 0:
+ if room_jid.find('/') >= 0:
+ room_jid, nick = room_jid.split('/', 1)
else:
- server = servernick
nick = ''
- #join_gc window is needed in order to provide for password entry.
+ # join_gc window is needed in order to provide for password entry.
if gajim.interface.instances[self.account].has_key('join_gc'):
gajim.interface.instances[self.account]['join_gc'].\
window.present()
@@ -1083,13 +1084,13 @@ class GroupchatControl(ChatControlBase):
try:
gajim.interface.instances[self.account]['join_gc'] =\
dialogs.JoinGroupchatWindow(self.account,
- server = server, room = room, nick = nick)
- except RuntimeError:
+ room_jid = room_jid, nick = nick)
+ except GajimGeneralException:
pass
self.clear(self.msg_textview)
else:
#%s is something the user wrote but it is not a jid so we inform
- s = _('%s does not appear to be a valid JID') % message_array
+ s = _('%s does not appear to be a valid JID') % message_array[0]
self.print_conversation(s, 'info')
else:
self.get_command_help(command)
@@ -1376,7 +1377,7 @@ class GroupchatControl(ChatControlBase):
if bookmark['jid'] == bm['jid']:
dialogs.ErrorDialog(
_('Bookmark already set'),
- _('Room "%s" is already in your bookmarks.') % bm['jid'])
+ _('Group Chat "%s" is already in your bookmarks.') % bm['jid'])
return
gajim.connections[self.account].bookmarks.append(bm)
@@ -1832,7 +1833,7 @@ class GroupchatControl(ChatControlBase):
present()
else:
gajim.interface.instances[self.account]['infos'][c2.jid] = \
- vcard.VcardWindow(c2, self.account, is_fake = True)
+ vcard.VcardWindow(c2, self.account, c)
def on_history(self, widget, nick):
jid = gajim.construct_fjid(self.room_jid, nick)
diff --git a/src/gtkexcepthook.py b/src/gtkexcepthook.py
index 1bc552a24..7e398979d 100644
--- a/src/gtkexcepthook.py
+++ b/src/gtkexcepthook.py
@@ -22,6 +22,7 @@ import threading
import gtk
import pango
+from common import i18n
import dialogs
from cStringIO import StringIO
diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py
index e1f094a29..e8608c511 100644
--- a/src/gtkgui_helpers.py
+++ b/src/gtkgui_helpers.py
@@ -169,33 +169,6 @@ def get_default_font():
return None
-def reduce_chars_newlines(text, max_chars = 0, max_lines = 0):
- '''Cut the chars after 'max_chars' on each line
- and show only the first 'max_lines'.
- If any of the params is not present (None or 0) the action
- on it is not performed'''
-
- def _cut_if_long(string):
- if len(string) > max_chars:
- string = string[:max_chars - 3] + '...'
- return string
-
- if isinstance(text, str):
- text = text.decode('utf-8')
-
- if max_lines == 0:
- lines = text.split('\n')
- else:
- lines = text.split('\n', max_lines)[:max_lines]
- if max_chars > 0:
- if lines:
- lines = map(lambda e: _cut_if_long(e), lines)
- if lines:
- reduced_text = reduce(lambda e, e1: e + '\n' + e1, lines)
- else:
- reduced_text = ''
- return reduced_text
-
def escape_for_pango_markup(string):
# escapes < > & ' "
# for pango markup not to break
@@ -210,7 +183,22 @@ def escape_for_pango_markup(string):
return escaped_str
def autodetect_browser_mailer():
- # recognize the environment for appropriate browser/mailer
+ # recognize the environment and set appropriate browser/mailer
+ if user_runs_gnome():
+ gajim.config.set('openwith', 'gnome-open')
+ elif user_runs_kde():
+ gajim.config.set('openwith', 'kfmclient exec')
+ else:
+ gajim.config.set('openwith', 'custom')
+
+def user_runs_gnome():
+ return 'gnome-session' in get_running_processes()
+
+def user_runs_kde():
+ return 'startkde' in get_running_processes()
+
+def get_running_processes():
+ '''returns running processes or None (if not /proc exists)'''
if os.path.isdir('/proc'):
# under Linux: checking if 'gnome-session' or
# 'startkde' programs were run before gajim, by
@@ -240,12 +228,8 @@ def autodetect_browser_mailer():
# list of processes
processes = [os.path.basename(os.readlink('/proc/' + f +'/exe')) for f in files]
- if 'gnome-session' in processes:
- gajim.config.set('openwith', 'gnome-open')
- elif 'startkde' in processes:
- gajim.config.set('openwith', 'kfmclient exec')
- else:
- gajim.config.set('openwith', 'custom')
+
+ return processes
def move_window(window, x, y):
'''moves the window but also checks if out of screen'''
diff --git a/src/history_manager.py b/src/history_manager.py
index a4bd75528..86810d3db 100755
--- a/src/history_manager.py
+++ b/src/history_manager.py
@@ -1,7 +1,4 @@
-#!/bin/sh
-''':'
-exec python -OOt "$0" ${1+"$@"}
-' '''
+#!/usr/bin/env python
## history_manager.py
##
## Copyright (C) 2006 Nikos Kouremenos
@@ -33,6 +30,9 @@ import dialogs
import gtkgui_helpers
from common.logger import LOG_DB_PATH, constants
+#FIXME: constants should implement 2 way mappings
+status = dict((constants.__dict__[i], i[5:].lower()) for i in \
+ constants.__dict__.keys() if i.startswith('SHOW_'))
from common import gajim
from common import helpers
@@ -51,7 +51,6 @@ except ImportError:
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)
@@ -312,6 +311,7 @@ class HistoryManager:
except ValueError:
pass
else:
+ color = None
if kind in (constants.KIND_SINGLE_MSG_RECV,
constants.KIND_CHAT_MSG_RECV, constants.KIND_GC_MSG):
# it is the other side
@@ -327,11 +327,14 @@ class HistoryManager:
message = ''
else:
message = ' : ' + message
- message = helpers.get_uf_show(show) + message
-
- message = '%s' % (color,
- gtkgui_helpers.escape_for_pango_markup(message))
- self.logs_liststore.append((log_line_id, jid_id, time_, message,
+ message = helpers.get_uf_show(gajim.SHOW_LIST[show]) + message
+
+ message_ = '%s' % \
+ gtkgui_helpers.escape_for_pango_markup(message)
+ self.logs_liststore.append((log_line_id, jid_id, time_, message_,
subject, nickname))
def _fill_search_results_listview(self, text):
diff --git a/src/history_window.py b/src/history_window.py
index e6c3f00fa..4a9bc9cec 100644
--- a/src/history_window.py
+++ b/src/history_window.py
@@ -59,7 +59,8 @@ class HistoryWindow:
self.calendar = xml.get_widget('calendar')
scrolledwindow = xml.get_widget('scrolledwindow')
- self.history_textview = conversation_textview.ConversationTextview(account)
+ self.history_textview = conversation_textview.ConversationTextview(
+ account, used_in_history_window = True)
scrolledwindow.add(self.history_textview.tv)
self.history_buffer = self.history_textview.tv.get_buffer()
self.history_buffer.create_tag('highlight', background = 'yellow')
@@ -209,7 +210,9 @@ class HistoryWindow:
if gajim.config.get('print_time') == 'always':
before_str = gajim.config.get('before_time')
+ before_str = helpers.from_one_line(before_str)
after_str = gajim.config.get('after_time')
+ after_str = helpers.from_one_line(after_str)
format = before_str + '%X' + after_str + ' '
tim = time.strftime(format, time.localtime(float(tim)))
buf.insert(end_iter, tim) # add time
@@ -277,7 +280,9 @@ class HistoryWindow:
if contact_name and kind != constants.KIND_GCSTATUS:
# add stuff before and after contact name
before_str = gajim.config.get('before_nickname')
+ before_str = helpers.from_one_line(before_str)
after_str = gajim.config.get('after_nickname')
+ after_str = helpers.from_one_line(after_str)
format = before_str + contact_name + after_str + ' '
buf.insert_with_tags_by_name(end_iter, format, tag_name)
diff --git a/src/notify.py b/src/notify.py
index b50aed37c..e4f34fbce 100644
--- a/src/notify.py
+++ b/src/notify.py
@@ -228,10 +228,10 @@ def notify(event, jid, account, parameters, advanced_notif_num = None):
text = message
elif message_type == 'pm': # private message
event_type = _('New Private Message')
- room_name, t = gajim.get_room_name_and_server_from_room_jid(jid)
+ room_name = gajim.get_nick_from_jid(jid)
img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
'priv_msg_recv.png')
- title = _('New Private Message from room %s') % room_name
+ title = _('New Private Message from group chat %s') % room_name
text = _('%(nickname)s: %(message)s') % {'nickname': nickname,
'message': message}
else: # chat message
diff --git a/src/roster_window.py b/src/roster_window.py
index 380e20c49..efdb723a3 100644
--- a/src/roster_window.py
+++ b/src/roster_window.py
@@ -35,6 +35,9 @@ import notify
from common import gajim
from common import helpers
+from common import passwords
+from common.exceptions import GajimGeneralException as GajimGeneralException
+
from message_window import MessageWindowMgr
from chat_control import ChatControl
from groupchat_control import GroupchatControl
@@ -192,6 +195,7 @@ class RosterWindow:
if self.regroup:
account = _('Merged accounts')
if not self.tree.row_expanded(path) and model.iter_has_child(iter):
+ # account row not expanded
model[iter][C_NAME] = '[%s]' % account
else:
model[iter][C_NAME] = account
@@ -512,7 +516,7 @@ class RosterWindow:
if contact.status and gajim.config.get('show_status_msgs_in_roster'):
status = contact.status.strip()
if status != '':
- status = gtkgui_helpers.reduce_chars_newlines(status, max_lines = 1)
+ status = helpers.reduce_chars_newlines(status, max_lines = 1)
# escape markup entities and make them small italic and fg color
color = gtkgui_helpers._get_fade_color(self.tree, selected, focus)
colorstring = "#%04x%04x%04x" % (color.red, color.green, color.blue)
@@ -609,13 +613,12 @@ class RosterWindow:
dialogs.ErrorDialog(_('You cannot join a room while you are invisible')
)
return
- room, server = room_jid.split('@')
if not gajim.interface.msg_win_mgr.has_window(room_jid, account):
self.new_room(room_jid, nick, account)
gc_win = gajim.interface.msg_win_mgr.get_window(room_jid, account)
gc_win.set_active_tab(room_jid, account)
gc_win.window.present()
- gajim.connections[account].join_gc(nick, room, server, password)
+ gajim.connections[account].join_gc(nick, room_jid, password)
if password:
gajim.gc_passwords[room_jid] = password
@@ -785,7 +788,9 @@ class RosterWindow:
disco_sub_menu = gtk.Menu()
new_chat_sub_menu = gtk.Menu()
- for account in gajim.connections:
+ accounts_list = gajim.contacts.get_accounts()
+ accounts_list.sort()
+ for account in accounts_list:
if gajim.connections[account].connected <= 1:
# if offline or connecting
continue
@@ -796,7 +801,8 @@ class RosterWindow:
label.set_use_underline(False)
gc_item = gtk.MenuItem()
gc_item.add(label)
- gc_item.connect('state-changed', gtkgui_helpers.on_bm_header_changed_state)
+ gc_item.connect('state-changed',
+ gtkgui_helpers.on_bm_header_changed_state)
gc_sub_menu.append(gc_item)
self.add_bookmarks_list(gc_sub_menu, account)
@@ -960,8 +966,8 @@ class RosterWindow:
item.connect('activate', self.on_history_manager_menuitem_activate)
def add_bookmarks_list(self, gc_sub_menu, account):
- '''Print join new room item and bookmarks list for an account'''
- item = gtk.MenuItem(_('_Join New Room'))
+ '''Show join new group chat item and bookmarks list for an account'''
+ item = gtk.MenuItem(_('_Join New Group Chat'))
item.connect('activate', self.on_join_gc_activate, account)
gc_sub_menu.append(item)
@@ -1690,9 +1696,9 @@ class RosterWindow:
try:
gajim.interface.instances[account]['join_gc'] = \
dialogs.JoinGroupchatWindow(account,
- server = gajim.connections[account].muc_jid[type_],
+ gajim.connections[account].muc_jid[type_],
automatic = {'invities': jid_list})
- except RuntimeError:
+ except GajimGeneralException:
continue
break
@@ -2048,7 +2054,7 @@ class RosterWindow:
model = self.tree.get_model()
account = model[iter][C_ACCOUNT].decode('utf-8')
- if account != 'all':
+ if account != 'all': # not in merged mode
menu = self.build_account_menu(account)
else:
menu = gtk.Menu()
@@ -2385,8 +2391,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
gajim.connections[account].password = passphrase
if save:
gajim.config.set_per('accounts', account, 'savepass', True)
- gajim.config.set_per('accounts', account, 'password',
- passphrase)
+ passwords.save_password(account, passphrase)
keyid = None
use_gpg_agent = gajim.config.get('use_gpg_agent')
@@ -2848,7 +2853,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
try:
gajim.interface.instances[account]['join_gc'] = \
dialogs.JoinGroupchatWindow(account)
- except RuntimeError:
+ except GajimGeneralException:
pass
def on_new_message_menuitem_activate(self, widget, account):
@@ -3138,7 +3143,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
def on_roster_treeview_row_expanded(self, widget, iter, path):
'''When a row is expanded change the icon of the arrow'''
model = self.tree.get_model()
- if gajim.config.get('mergeaccounts'):
+ if self.regroup: # merged accounts
accounts = gajim.connections.keys()
else:
accounts = [model[iter][C_ACCOUNT].decode('utf-8')]
@@ -3170,7 +3175,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
'''When a row is collapsed :
change the icon of the arrow'''
model = self.tree.get_model()
- if gajim.config.get('mergeaccounts'):
+ if self.regroup: # merged accounts
accounts = gajim.connections.keys()
else:
accounts = [model[iter][C_ACCOUNT].decode('utf-8')]
@@ -3287,7 +3292,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
try:
# Object will add itself to the window dict
disco.ServiceDiscoveryWindow(account, address_entry = True)
- except RuntimeError:
+ except GajimGeneralException:
pass
def load_iconset(self, path, pixbuf2 = None, transport = False):
diff --git a/src/rst_xhtml_generator.py b/src/rst_xhtml_generator.py
deleted file mode 100644
index c44d3a9d8..000000000
--- a/src/rst_xhtml_generator.py
+++ /dev/null
@@ -1,116 +0,0 @@
-## rst_xhtml_generator.py
-##
-## Copyright (C) 2006 Yann Le Boulanger
-## Copyright (C) 2006 Nikos Kouremenos
-## Copyright (C) 2006 Santiago Gala
-##
-## This program is free software; you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published
-## by the Free Software Foundation; version 2 only.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-## GNU General Public License for more details.
-##
-
-from docutils import io
-from docutils.core import Publisher
-from docutils.parsers.rst import roles
-
-def jep_reference_role(role, rawtext, text, lineno, inliner,
- options={}, content=[]):
- '''Role to make handy references to Jabber Enhancement Proposals (JEP).
-
- Use as :JEP:`71` (or jep, or jep-reference).
- Modeled after the sample in docutils documentation.
- '''
- from docutils import nodes,utils
- from docutils.parsers.rst.roles import set_classes
-
- jep_base_url = 'http://www.jabber.org/jeps/'
- jep_url = 'jep-%04d.html'
- try:
- jepnum = int(text)
- if jepnum <= 0:
- raise ValueError
- except ValueError:
- msg = inliner.reporter.error(
- 'JEP number must be a number greater than or equal to 1; '
- '"%s" is invalid.' % text, line=lineno)
- prb = inliner.problematic(rawtext, rawtext, msg)
- return [prb], [msg]
- ref = jep_base_url + jep_url % jepnum
- set_classes(options)
- node = nodes.reference(rawtext, 'JEP ' + utils.unescape(text), refuri=ref,
- **options)
- return [node], []
-
-roles.register_canonical_role('jep-reference', jep_reference_role)
-from docutils.parsers.rst.languages.en import roles
-roles['jep-reference'] = 'jep-reference'
-roles['jep'] = 'jep-reference'
-
-class HTMLGenerator:
- '''Really simple HTMLGenerator starting from publish_parts.
-
- It reuses the docutils.core.Publisher class, which means it is *not*
- threadsafe.
- '''
- def __init__(self,
- settings_spec=None,
- settings_overrides=dict(report_level=5, halt_level=5),
- config_section='general'):
- self.pub = Publisher(reader=None, parser=None, writer=None,
- settings=None,
- source_class=io.StringInput,
- destination_class=io.StringOutput)
- self.pub.set_components(reader_name='standalone',
- parser_name='restructuredtext',
- writer_name='html')
- #hack: JEP-0071 does not allow HTML char entities, so we hack our way out of it.
- # — == u"\u2014"
- # a setting to only emit charater entities in the writer would be nice
- # FIXME: several are emitted, and they are explicitly forbidden in the JEP
- # == u"\u00a0"
- self.pub.writer.translator_class.attribution_formats['dash'] = (u'\u2014', '')
- self.pub.process_programmatic_settings(settings_spec,
- settings_overrides,
- config_section)
-
-
- def create_xhtml(self, text,
- destination=None,
- destination_path=None,
- enable_exit_status=None):
- ''' Create xhtml for a fragment of IM dialog.
- We can use the source_name to store info about
- the message.'''
- self.pub.set_source(text, None)
- self.pub.set_destination(destination, destination_path)
- output = self.pub.publish(enable_exit_status=enable_exit_status)
- #kludge until we can get docutils to stop generating (rare) entities
- return u'\u00a0'.join(self.pub.writer.parts['fragment'].strip().split(' '))
-
-Generator = HTMLGenerator()
-
-def create_xhtml(text):
- return Generator.create_xhtml(text)
-
-if __name__ == '__main__':
- print Generator.create_xhtml('''
-test::
-
- >>> print 1
- 1
-
-*I* like it. It is for :JEP:`71`
-
-this `` should trigger`` should trigger the problem.
-
-''')
- print Generator.create_xhtml('''
-*test1
-
-test2_
-''')
diff --git a/src/statusicon.py b/src/statusicon.py
new file mode 100644
index 000000000..f6e785ce9
--- /dev/null
+++ b/src/statusicon.py
@@ -0,0 +1,69 @@
+## statusicon.py
+##
+## Copyright (C) 2006 Nikos Kouremenos
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License
+## as published by the Free Software Foundation; either version 2
+## of the License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+
+import gtk
+import gobject
+import systray
+
+from common import gajim
+from common import helpers
+
+class StatusIcon(systray.Systray):
+ '''Class for the notification area icon'''
+ #FIXME: when we migrate to GTK 2.10 stick only to this class
+ # (move base stuff from systray.py and rm it)
+ #NOTE: gtk api does NOT allow:
+ # leave, enter motion notify
+ # and can't do cool tooltips we use
+ # and we could use blinking instead of unsupported animation
+ # or we could emulate animation by every foo ms chaning the image
+ def __init__(self):
+ systray.Systray.__init__(self)
+ self.status_icon = gtk.StatusIcon()
+
+ def show_icon(self):
+ self.status_icon.connect('activate', self.on_status_icon_left_clicked)
+ self.status_icon.connect('popup-menu', self.on_status_icon_right_clicked)
+
+ self.set_img()
+ self.status_icon.props.visible = True
+
+ def on_status_icon_right_clicked(self, widget, event_button, event_time):
+ self.make_menu(event_button, event_time)
+
+ def hide_icon(self):
+ self.status_icon.props.visible = False
+
+ def on_status_icon_left_clicked(self, widget):
+ self.on_left_click()
+
+ def set_img(self):
+ '''apart from image, we also update tooltip text here'
+ if not gajim.interface.systray_enabled:
+ return
+ text = helpers.get_notification_icon_tooltip_text()
+ self.status_icon.set_tooltip(text)
+ if gajim.events.get_nb_systray_events():
+ state = 'message'
+ else:
+ state = self.status
+ #FIXME: do not always use 16x16 (ask actually used size and use that)
+ image = gajim.interface.roster.jabber_state_images['16'][state]
+ if image.get_storage_type() == gtk.IMAGE_PIXBUF:
+ self.status_icon.props.pixbuf = image.get_pixbuf()
+ #FIXME: oops they forgot to support GIF animation?
+ #or they were lazy to get it to work under Windows! WTF!
+ #elif image.get_storage_type() == gtk.IMAGE_ANIMATION:
+ # self.img_tray.set_from_animation(image.get_animation())
diff --git a/src/systray.py b/src/systray.py
index ade7ffd81..607739756 100644
--- a/src/systray.py
+++ b/src/systray.py
@@ -43,7 +43,7 @@ except:
class Systray:
'''Class for icon in the notification area
- This class is both base class (for systraywin32.py) and normal class
+ This class is both base class (for statusicon.py) and normal class
for trayicon in GNU/Linux'''
def __init__(self):
@@ -94,16 +94,14 @@ class Systray:
def on_new_chat(self, widget, account):
dialogs.NewChatDialog(account)
- def make_menu(self, event = None):
- '''create chat with and new message (sub) menus/menuitems
- event is None when we're in Windows
- '''
-
+ def make_menu(self, event_button, event_time):
+ '''create chat with and new message (sub) menus/menuitems'''
for m in self.popup_menus:
m.destroy()
chat_with_menuitem = self.xml.get_widget('chat_with_menuitem')
- single_message_menuitem = self.xml.get_widget('single_message_menuitem')
+ single_message_menuitem = self.xml.get_widget(
+ 'single_message_menuitem')
status_menuitem = self.xml.get_widget('status_menu')
join_gc_menuitem = self.xml.get_widget('join_gc_menuitem')
@@ -171,7 +169,8 @@ class Systray:
self.popup_menus.append(account_menu_for_chat_with)
account_menu_for_single_message = gtk.Menu()
- single_message_menuitem.set_submenu(account_menu_for_single_message)
+ single_message_menuitem.set_submenu(
+ account_menu_for_single_message)
self.popup_menus.append(account_menu_for_single_message)
accounts_list = gajim.contacts.get_accounts()
@@ -195,9 +194,11 @@ class Systray:
label.set_use_underline(False)
gc_item = gtk.MenuItem()
gc_item.add(label)
- gc_item.connect('state-changed', gtkgui_helpers.on_bm_header_changed_state)
+ gc_item.connect('state-changed',
+ gtkgui_helpers.on_bm_header_changed_state)
gc_sub_menu.append(gc_item)
- gajim.interface.roster.add_bookmarks_list(gc_sub_menu, account)
+ gajim.interface.roster.add_bookmarks_list(gc_sub_menu,
+ account)
elif connected_accounts == 1: # one account
# one account connected, no need to show 'as jid'
@@ -207,24 +208,24 @@ class Systray:
'activate', self.on_new_chat, account)
# for single message
single_message_menuitem.remove_submenu()
- self.single_message_handler_id = single_message_menuitem.connect(
- 'activate', self.on_single_message_menuitem_activate, account)
+ self.single_message_handler_id = single_message_menuitem.\
+ connect('activate',
+ self.on_single_message_menuitem_activate, account)
# join gc
- gajim.interface.roster.add_bookmarks_list(gc_sub_menu, account)
+ gajim.interface.roster.add_bookmarks_list(gc_sub_menu,
+ account)
break # No other connected account
- if event is None:
- # None means windows (we explicitly popup in systraywin32.py)
- if self.added_hide_menuitem is False:
- self.systray_context_menu.prepend(gtk.SeparatorMenuItem())
- item = gtk.MenuItem(_('Hide this menu'))
- self.systray_context_menu.prepend(item)
- self.added_hide_menuitem = True
+ if os.name == 'nt' and gtk.pygtk_version >= (2, 10, 0) and\
+ gtk.gtk_version >= (2, 10, 0):
+ self.systray_context_menu.popup(None, None,
+ gtk.status_icon_position_menu, event_button,
+ event_time, self.status_icon)
else: # GNU and Unices
- self.systray_context_menu.popup(None, None, None, event.button,
- event.time)
+ self.systray_context_menu.popup(None, None, None, event_button,
+ event_time)
self.systray_context_menu.show_all()
def on_show_all_events_menuitem_activate(self, widget):
@@ -277,12 +278,14 @@ class Systray:
def on_clicked(self, widget, event):
self.on_tray_leave_notify_event(widget, None)
- if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1: # Left click
+ if event.type != gtk.gdk.BUTTON_PRESS:
+ return
+ if event.button == 1: # Left click
self.on_left_click()
elif event.button == 2: # middle click
self.on_middle_click()
elif event.button == 3: # right click
- self.make_menu(event)
+ self.make_menu(event.button, event.time)
def on_show_menuitem_activate(self, widget, show):
# we all add some fake (we cannot select those nor have them as show)
diff --git a/src/tooltips.py b/src/tooltips.py
index 53915df8a..66989f12d 100644
--- a/src/tooltips.py
+++ b/src/tooltips.py
@@ -38,7 +38,7 @@ class BaseTooltip:
tooltip.hide_tooltip()
* data - the text to be displayed (extenders override this argument and
- dislpay more complex contents)
+ display more complex contents)
* widget_height - the height of the widget on which we want to show tooltip
* widget_y_position - the vertical position of the widget on the screen
@@ -135,7 +135,7 @@ class BaseTooltip:
preferred_y = widget_y_position + widget_height + 4
self.preferred_position = [pointer_x, preferred_y]
- self.widget_height =widget_height
+ self.widget_height = widget_height
self.win.ensure_style()
self.win.show_all()
@@ -177,10 +177,12 @@ class StatusTable:
# make sure 'status' is unicode before we send to to reduce_chars
if isinstance(status, str):
status = unicode(status, encoding='utf-8')
- # reduce to 200 chars, 1 line
- status = gtkgui_helpers.reduce_chars_newlines(status, 200, 1)
- str_status += ' - ' + status
- return gtkgui_helpers.escape_for_pango_markup(str_status)
+ # reduce to 100 chars, 1 line
+ status = helpers.reduce_chars_newlines(status, 100, 1)
+ str_status = gtkgui_helpers.escape_for_pango_markup(str_status)
+ status = gtkgui_helpers.escape_for_pango_markup(status)
+ str_status += ' - ' + status + ''
+ return str_status
def add_status_row(self, file_path, show, str_status, status_time = None, show_lock = False):
''' appends a new row with status icon to the table '''
@@ -227,27 +229,6 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable):
BaseTooltip.__init__(self)
StatusTable.__init__(self)
- def get_accounts_info(self):
- accounts = []
- accounts_list = gajim.contacts.get_accounts()
- accounts_list.sort()
- for account in accounts_list:
- status_idx = gajim.connections[account].connected
- # uncomment the following to hide offline accounts
- # if status_idx == 0: continue
- status = gajim.SHOW_LIST[status_idx]
- message = gajim.connections[account].status
- single_line = helpers.get_uf_show(status)
- if message is None:
- message = ''
- else:
- message = message.strip()
- if message != '':
- single_line += ': ' + message
- accounts.append({'name': account, 'status_line': single_line,
- 'show': status, 'message': message})
- return accounts
-
def fill_table_with_accounts(self, accounts):
iconset = gajim.config.get('iconset')
if not iconset:
@@ -259,7 +240,7 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable):
# there are possible pango TBs on 'set_markup'
if isinstance(message, str):
message = unicode(message, encoding = 'utf-8')
- message = gtkgui_helpers.reduce_chars_newlines(message, 50, 1)
+ message = helpers.reduce_chars_newlines(message, 100, 1)
message = gtkgui_helpers.escape_for_pango_markup(message)
if gajim.con_types.has_key(acct['name']) and \
gajim.con_types[acct['name']] in ('tls', 'ssl'):
@@ -278,67 +259,16 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable):
def populate(self, data):
self.create_window()
self.create_table()
- self.hbox = gtk.HBox()
- self.table.set_property('column-spacing', 1)
- text, single_line = '', ''
-
- unread_chat = gajim.events.get_nb_events(types = ['printed_chat', 'chat'])
- unread_single_chat = gajim.events.get_nb_events(types = ['normal'])
- unread_gc = gajim.events.get_nb_events(types = ['printed_gc_msg',
- 'gc_msg'])
- unread_pm = gajim.events.get_nb_events(types = ['printed_pm', 'pm'])
-
- accounts = self.get_accounts_info()
-
- if unread_chat or unread_single_chat or unread_gc or unread_pm:
- text = 'Gajim '
- awaiting_events = unread_chat + unread_single_chat + unread_gc + unread_pm
- if awaiting_events == unread_chat or awaiting_events == unread_single_chat \
- or awaiting_events == unread_gc or awaiting_events == unread_pm:
- # This condition is like previous if but with xor...
- # Print in one line
- text += '-'
- else:
- # Print in multiple lines
- text += '\n '
- if unread_chat:
- text += i18n.ngettext(
- ' %d unread message',
- ' %d unread messages',
- unread_chat, unread_chat, unread_chat)
- text += '\n '
- if unread_single_chat:
- text += i18n.ngettext(
- ' %d unread single message',
- ' %d unread single messages',
- unread_single_chat, unread_single_chat, unread_single_chat)
- text += '\n '
- if unread_gc:
- text += i18n.ngettext(
- ' %d unread group chat message',
- ' %d unread group chat messages',
- unread_gc, unread_gc, unread_gc)
- text += '\n '
- if unread_pm:
- text += i18n.ngettext(
- ' %d unread private message',
- ' %d unread private messages',
- unread_pm, unread_pm, unread_pm)
- text += '\n '
- text = text[:-4] # remove latest '\n '
- elif len(accounts) > 1:
- text = _('Gajim')
- self.current_current_row = 1
+ accounts = helpers.get_accounts_info()
+ if len(accounts) > 1:
self.table.resize(2, 1)
self.fill_table_with_accounts(accounts)
+ self.hbox = gtk.HBox()
+ self.table.set_property('column-spacing', 1)
- elif len(accounts) == 1:
- message = accounts[0]['status_line']
- message = gtkgui_helpers.reduce_chars_newlines(message, 50, 1)
- message = gtkgui_helpers.escape_for_pango_markup(message)
- text = _('Gajim - %s') % message
- else:
- text = _('Gajim - %s') % helpers.get_uf_show('offline')
+ text = helpers.get_notification_icon_tooltip_text()
+ text = gtkgui_helpers.escape_for_pango_markup(text)
+
self.add_text_row(text)
self.hbox.add(self.table)
self.win.add(self.hbox)
@@ -364,7 +294,25 @@ class GCTooltip(BaseTooltip):
vcard_table.set_homogeneous(False)
vcard_current_row = 1
properties = []
-
+
+ nick_markup = '' + \
+ gtkgui_helpers.escape_for_pango_markup(contact.get_shown_name()) \
+ + ''
+ properties.append((nick_markup, None))
+
+ if contact.status: # status message
+ status = contact.status.strip()
+ if status != '':
+ # escape markup entities
+ status = helpers.reduce_chars_newlines(status, 100, 5)
+ status = '' +\
+ gtkgui_helpers.escape_for_pango_markup(status) + ''
+ properties.append((status, None))
+ else: # no status message, show SHOW instead
+ show = helpers.get_uf_show(contact.show)
+ show = '' + show + ''
+ properties.append((show, None))
+
if contact.jid.strip() != '':
jid_markup = '' + contact.jid + ''
else:
@@ -445,8 +393,7 @@ class RosterTooltip(NotificationAreaTooltip):
self.create_table()
if not contacts or len(contacts) == 0:
# Tooltip for merged accounts row
- accounts = self.get_accounts_info()
- self.current_current_row = 0
+ accounts = helpers.get_accounts_info()
self.table.resize(2, 1)
self.spacer_label = ''
self.fill_table_with_accounts(accounts)
@@ -539,8 +486,8 @@ class RosterTooltip(NotificationAreaTooltip):
status = contact.status.strip()
if status:
# reduce long status
- # (no more than 200 chars on line and no more than 5 lines)
- status = gtkgui_helpers.reduce_chars_newlines(status, 200, 5)
+ # (no more than 100 chars on line and no more than 5 lines)
+ status = helpers.reduce_chars_newlines(status, 100, 5)
# escape markup entities.
status = gtkgui_helpers.escape_for_pango_markup(status)
show += ' - ' + status
diff --git a/src/vcard.py b/src/vcard.py
index 0ee005e72..48bb83efc 100644
--- a/src/vcard.py
+++ b/src/vcard.py
@@ -60,7 +60,7 @@ def get_avatar_pixbuf_encoded_mime(photo):
class VcardWindow:
'''Class for contact's information window'''
- def __init__(self, contact, account, is_fake = False):
+ def __init__(self, contact, account, gc_contact = None):
# the contact variable is the jid if vcard is true
self.xml = gtkgui_helpers.get_glade('vcard_information_window.glade')
self.window = self.xml.get_widget('vcard_information_window')
@@ -68,7 +68,7 @@ class VcardWindow:
self.contact = contact
self.account = account
- self.is_fake = is_fake
+ self.gc_contact = gc_contact
self.avatar_mime_type = None
self.avatar_encoded = None
@@ -246,26 +246,38 @@ class VcardWindow:
self.contact.get_shown_name() +
'')
self.xml.get_widget('jid_label').set_text(self.contact.jid)
- uf_sub = helpers.get_uf_sub(self.contact.sub)
- self.xml.get_widget('subscription_label').set_text(uf_sub)
- eb = self.xml.get_widget('subscription_label_eventbox')
- if self.contact.sub == 'from':
- tt_text = _("This contact is interested in your presence information, but you are not interested in his/her presence")
- elif self.contact.sub == 'to':
- tt_text = _("You are interested in the contact's presence information, but he/she is not interested in yours")
- elif self.contact.sub == 'both':
- tt_text = _("You and the contact are interested in each other's presence information")
- else: # None
- tt_text = _("You are not interested in the contact's presence, and neither he/she is interested in yours")
- tooltips.set_tip(eb, tt_text)
+
+ subscription_label = self.xml.get_widget('subscription_label')
+ ask_label = self.xml.get_widget('ask_label')
+ if self.gc_contact:
+ self.xml.get_widget('subscription_title_label').set_text(_("Role:"))
+ uf_role = helpers.get_uf_role(self.gc_contact.role)
+ subscription_label.set_text(uf_role)
+
+ self.xml.get_widget('ask_title_label').set_text(_("Affiliation:"))
+ uf_affiliation = helpers.get_uf_affiliation(self.gc_contact.affiliation)
+ ask_label.set_text(uf_affiliation)
+ else:
+ uf_sub = helpers.get_uf_sub(self.contact.sub)
+ subscription_label.set_text(uf_sub)
+ eb = self.xml.get_widget('subscription_label_eventbox')
+ if self.contact.sub == 'from':
+ tt_text = _("This contact is interested in your presence information, but you are not interested in his/her presence")
+ elif self.contact.sub == 'to':
+ tt_text = _("You are interested in the contact's presence information, but he/she is not interested in yours")
+ elif self.contact.sub == 'both':
+ tt_text = _("You and the contact are interested in each other's presence information")
+ else: # None
+ tt_text = _("You are not interested in the contact's presence, and neither he/she is interested in yours")
+ tooltips.set_tip(eb, tt_text)
+
+ uf_ask = helpers.get_uf_ask(self.contact.ask)
+ ask_label.set_text(uf_ask)
+ eb = self.xml.get_widget('ask_label_eventbox')
+ if self.contact.ask == 'subscribe':
+ tooltips.set_tip(eb,
+ _("You are waiting contact's answer about your subscription request"))
- label = self.xml.get_widget('ask_label')
- uf_ask = helpers.get_uf_ask(self.contact.ask)
- label.set_text(uf_ask)
- eb = self.xml.get_widget('ask_label_eventbox')
- if self.contact.ask == 'subscribe':
- tooltips.set_tip(eb,
- _("You are waiting contact's answer about your subscription request"))
log = True
if self.contact.jid in gajim.config.get_per('accounts', self.account,
'no_log_for').split(' '):
@@ -318,7 +330,8 @@ class VcardWindow:
self.fill_status_label()
- gajim.connections[self.account].request_vcard(self.contact.jid, self.is_fake)
+ gajim.connections[self.account].request_vcard(self.contact.jid,
+ self.gc_contact is not None)
def on_close_button_clicked(self, widget):
self.window.destroy()