merge with trunk
This commit is contained in:
parent
cd4c823eb5
commit
0d0ac51fa8
40 changed files with 1042 additions and 1107 deletions
2
AUTHORS
2
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)
|
||||
|
|
208
ChangeLog
208
ChangeLog
|
@ -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 <body> 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.
|
12
Changelog
12
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
|
||||
|
|
86
README
86
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
|
||||
|
|
130
README.html
Normal file
130
README.html
Normal file
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>Gajim - Read Me</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Gajim Read Me</h1>
|
||||
|
||||
<p>
|
||||
Welcome to Gajim and thank you for trying out our client.
|
||||
</p>
|
||||
|
||||
<h2>Runtime Requirements</h2>
|
||||
<ul>
|
||||
<li>python2.4 or higher</li>
|
||||
<li>pygtk2.6 or higher</li>
|
||||
<li>python-libglade</li>
|
||||
<li>pysqlite2 (if you have python 2.5, you already have this)</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<strong>Note to packagers</strong>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h2>Optional Runtime Requirements</h2>
|
||||
<ul>
|
||||
<li>dnsutils (or whatever package provides the nslookup binary) for SRV support; if you don't know what that is, you don't need it</li>
|
||||
<li>gtkspell and aspell-LANG where lang is your locale eg. en, fr etc</li>
|
||||
<li>GnomePythonExtras 2.10 or above (aka gnome-python-desktop) so you can avoid compiling trayicon and gtkspell</li>
|
||||
<li>gnome-python-desktop (for GnomeKeyring support)</li>
|
||||
<li>notification-daemon or notify-python (and D-Bus) to get cooler popups</li>
|
||||
<li>D-Bus to have gajim-remote working</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h2>Compile-time Requirements</h2>
|
||||
<ul>
|
||||
<li>python-dev</li>
|
||||
<li>python-gtk2-dev</li>
|
||||
<li>libgtk2.0-dev aka. gtk2-devel</li>
|
||||
<li>libxss-dev (for idle detection module; some distributions such as Debian split xscreensaver)</li>
|
||||
<li>libgtkspell-dev (for the gtkspell module)</li>
|
||||
<li>intltool</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<strong>NOTE:</strong>
|
||||
If you still have problems compiling, you may want to try removing the gtk1 series of the above dependencies.
|
||||
</p>
|
||||
|
||||
<h2>Installation Procedure</h2>
|
||||
<ol>
|
||||
<li>tar jxvf gajim-version.tar.bz2</li>
|
||||
</li>cd gajim</li>
|
||||
</li>make (builds all modules)</li>
|
||||
</li>su -c make install</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
To specify what modules to build do:
|
||||
make help
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To specify where to install do:
|
||||
su -c make PREFIX=custom_path install
|
||||
</p>
|
||||
|
||||
<h2>Running Gajim</h2>
|
||||
<p>
|
||||
Just do <em>gajim</em> or you can run Gajim from your GNOME/XFCE/KDE/whatever menus.<br/><br/>
|
||||
|
||||
or if you didn't 'make install' you can also run from gajim folder with
|
||||
<em>./launch.sh</em>
|
||||
</p>
|
||||
|
||||
<h2>Uninstallation Procedure</h2>
|
||||
<p>
|
||||
su -c make uninstall<br/>
|
||||
this will try to remove Gajim from the default directories.
|
||||
If you want to remove it from custom directory provide it as:<br/>
|
||||
make PREFIX=custom_path uninstall
|
||||
</p>
|
||||
|
||||
<h2>Miscellaneous</h2>
|
||||
<h3>XML & Debugging</h3>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h3>FAQ/Wiki</h3>
|
||||
<p>
|
||||
FAQ can be found at <a href="http://trac.gajim.org/wiki/GajimFaq">http://trac.gajim.org/wiki/GajimFaq</a><br/>
|
||||
Wiki can be found at <a href="http://trac.gajim.org/wiki">http://trac.gajim.org/wiki</a>
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
That is all, <strong>enjoy!</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
(C) 2003-2006<br/>
|
||||
The Gajim Team<br/>
|
||||
http://gajim.org<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
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.
|
||||
</p>
|
||||
</body></html>
|
|
@ -17,6 +17,7 @@
|
|||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="urgency_hint">False</property>
|
||||
<signal name="destroy" handler="on_join_groupchat_window_destroy" last_modification_time="Wed, 02 Mar 2005 12:20:14 GMT"/>
|
||||
<signal name="key_press_event" handler="on_join_groupchat_window_key_press_event" last_modification_time="Tue, 05 Apr 2005 13:13:40 GMT"/>
|
||||
|
||||
|
@ -29,58 +30,14 @@
|
|||
<child>
|
||||
<widget class="GtkTable" id="table15">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">5</property>
|
||||
<property name="n_rows">4</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">12</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="password_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">False</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="server_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">True</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">True</property>
|
||||
<signal name="key_press_event" handler="on_server_entry_key_press_event" last_modification_time="Fri, 25 Nov 2005 22:09:39 GMT"/>
|
||||
<signal name="changed" handler="on_required_entry_changed" last_modification_time="Sat, 14 Jan 2006 21:51:55 GMT"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="room_entry">
|
||||
<widget class="GtkEntry" id="room_jid_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="has_focus">True</property>
|
||||
|
@ -91,7 +48,6 @@
|
|||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">True</property>
|
||||
<signal name="key_press_event" handler="on_room_entry_key_press_event" last_modification_time="Fri, 25 Nov 2005 22:07:30 GMT"/>
|
||||
<signal name="changed" handler="on_required_entry_changed" last_modification_time="Sat, 14 Jan 2006 21:51:39 GMT"/>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -125,62 +81,6 @@
|
|||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label145">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Password:</property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label144">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Server:</property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label143">
|
||||
<property name="visible">True</property>
|
||||
|
@ -281,6 +181,55 @@
|
|||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label145">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Password:</property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="password_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">False</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
|
|
|
@ -900,7 +900,6 @@ Per type</property>
|
|||
<widget class="GtkFontButton" id="conversation_fontbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="title" translatable="yes">Επιλογή μιας γραμματοσειράς</property>
|
||||
<property name="show_style">True</property>
|
||||
<property name="show_size">True</property>
|
||||
<property name="use_font">False</property>
|
||||
|
@ -952,7 +951,6 @@ Per type</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="use_alpha">False</property>
|
||||
<property name="title" translatable="yes">Επιλογή χρώματος</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="color_set" handler="on_outgoing_msg_colorbutton_color_set" last_modification_time="Sun, 06 Mar 2005 14:07:56 GMT"/>
|
||||
</widget>
|
||||
|
@ -971,7 +969,6 @@ Per type</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="use_alpha">False</property>
|
||||
<property name="title" translatable="yes">Επιλογή χρώματος</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="color_set" handler="on_url_msg_colorbutton_color_set" last_modification_time="Sun, 25 Dec 2005 15:22:17 GMT"/>
|
||||
</widget>
|
||||
|
@ -1051,7 +1048,6 @@ Per type</property>
|
|||
<property name="can_focus">True</property>
|
||||
<property name="has_focus">True</property>
|
||||
<property name="use_alpha">False</property>
|
||||
<property name="title" translatable="yes">Επιλογή χρώματος</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="color_set" handler="on_incoming_msg_colorbutton_color_set" last_modification_time="Sun, 06 Mar 2005 14:07:44 GMT"/>
|
||||
</widget>
|
||||
|
@ -1070,7 +1066,6 @@ Per type</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="use_alpha">False</property>
|
||||
<property name="title" translatable="yes">Επιλογή χρώματος</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="color_set" handler="on_status_msg_colorbutton_color_set" last_modification_time="Sun, 06 Mar 2005 14:08:04 GMT"/>
|
||||
</widget>
|
||||
|
|
|
@ -448,7 +448,7 @@
|
|||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label45">
|
||||
<widget class="GtkLabel" id="subscription_title_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes" comments="Family Name">Subscription:</property>
|
||||
<property name="use_underline">False</property>
|
||||
|
@ -476,7 +476,7 @@
|
|||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label46">
|
||||
<widget class="GtkLabel" id="ask_title_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes" comments="Given Name">Ask:</property>
|
||||
<property name="use_underline">False</property>
|
||||
|
|
114
po/POTFILES.in
114
po/POTFILES.in
|
@ -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
|
4
po/de.po
4
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"
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
## advanced.py
|
||||
##
|
||||
## Contributors for this file:
|
||||
## - Yann Le Boulanger <asterix@lagaule.org>
|
||||
## - Nikos Kouremenos <kourem@gmail.com>
|
||||
## - Vincent Hanquez <tab@snarc.org>
|
||||
##
|
||||
## Copyright (C) 2003-2004 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Copyright (C) 2005 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Nikos Kouremenos <kourem@gmail.com>
|
||||
## Dimitur Kirov <dkirov@gmail.com>
|
||||
## Travis Shirk <travis@pobox.com>
|
||||
## Norman Rasmussen <norman@rasmussen.co.za>
|
||||
## Copyright (C) 2005-2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
## Copyright (C) 2005 Vincent Hanquez <tab@snarc.org>
|
||||
##
|
||||
## 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')
|
||||
|
|
|
@ -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 = '<body xmlns="%s">%s</body>' % (NS_XHTML, create_xhtml(text))
|
||||
xhtml = create_xhtml(text)
|
||||
if xhtml:
|
||||
xhtml = '<body xmlns="%s">%s</body>' % (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:
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
## Contributors for this file:
|
||||
## - Yann Le Boulanger <asterix@lagaule.org>
|
||||
## - Nikos Kouremenos <kourem@gmail.com>
|
||||
## - Travis Shirk <travis@pobox.com>
|
||||
##
|
||||
## Copyright (C) 2003-2004 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Copyright (C) 2005 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Nikos Kouremenos <kourem@gmail.com>
|
||||
## Dimitur Kirov <dkirov@gmail.com>
|
||||
## Travis Shirk <travis@pobox.com>
|
||||
## Norman Rasmussen <norman@rasmussen.co.za>
|
||||
## Copyright (C) 2005-2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
## Copyright (C) 2005-2006 Travis Shirk <travis@pobox.com>
|
||||
##
|
||||
## 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);
|
||||
'''
|
||||
)
|
||||
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
## exceptions.py
|
||||
##
|
||||
## Contributors for this file:
|
||||
## - Yann Le Boulanger <asterix@lagaule.org>
|
||||
## -
|
||||
##
|
||||
## Copyright (C) 2005-2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Nikos Kouremenos <kourem@gmail.com>
|
||||
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
##
|
||||
## 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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
## logger.py
|
||||
##
|
||||
## Contributors for this file:
|
||||
## - Yann Le Boulanger <asterix@lagaule.org>
|
||||
## - Nikos Kouremenos <kourem@gmail.com>
|
||||
##
|
||||
## Copyright (C) 2003-2004 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Copyright (C) 2005 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Nikos Kouremenos <kourem@gmail.com>
|
||||
## Dimitur Kirov <dkirov@gmail.com>
|
||||
## Travis Shirk <travis@pobox.com>
|
||||
## Norman Rasmussen <norman@rasmussen.co.za>
|
||||
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
## Copyright (C) 2005-2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
##
|
||||
## 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
|
||||
|
|
|
@ -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')
|
||||
|
|
85
src/common/passwords.py
Normal file
85
src/common/passwords.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
##
|
||||
## Copyright (C) 2006 Gustavo J. A. M. Carneiro <gjcarneiro@gmail.com>
|
||||
## Copyright (C) 2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
##
|
||||
## 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)
|
126
src/common/rst_xhtml_generator.py
Normal file
126
src/common/rst_xhtml_generator.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
## rst_xhtml_generator.py
|
||||
##
|
||||
## Copyright (C) 2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Copyright (C) 2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
## 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_
|
||||
''')
|
|
@ -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()
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
## conversation_textview.py
|
||||
##
|
||||
## Contributors for this file:
|
||||
## - Yann Le Boulanger <asterix@lagaule.org>
|
||||
## - Nikos Kouremenos <kourem@gmail.com>
|
||||
##
|
||||
## Copyright (C) 2003-2004 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Copyright (C) 2005 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Nikos Kouremenos <kourem@gmail.com>
|
||||
## Dimitur Kirov <dkirov@gmail.com>
|
||||
## Travis Shirk <travis@pobox.com>
|
||||
## Norman Rasmussen <norman@rasmussen.co.za>
|
||||
## Copyright (C) 2005-2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
## Copyright (C) 2005-2006 Travis Shirk <travis@pobox.com>
|
||||
##
|
||||
## 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':
|
||||
|
|
108
src/dialogs.py
108
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:
|
||||
|
|
47
src/disco.py
47
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()
|
||||
|
|
67
src/gajim.py
67
src/gajim.py
|
@ -4,20 +4,11 @@ exec python -OOt "$0" ${1+"$@"}
|
|||
' '''
|
||||
## gajim.py
|
||||
##
|
||||
## Contributors for this file:
|
||||
## - Yann Le Boulanger <asterix@lagaule.org>
|
||||
## - Nikos Kouremenos <kourem@gmail.com>
|
||||
## - Dimitur Kirov <dkirov@gmail.com>
|
||||
## - Travis Shirk <travis@pobox.com>
|
||||
##
|
||||
## Copyright (C) 2003-2004 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Copyright (C) 2005 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Vincent Hanquez <tab@snarc.org>
|
||||
## Nikos Kouremenos <kourem@gmail.com>
|
||||
## Dimitur Kirov <dkirov@gmail.com>
|
||||
## Travis Shirk <travis@pobox.com>
|
||||
## Norman Rasmussen <norman@rasmussen.co.za>
|
||||
## Copyright (C) 2003-2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov@gmail.com>
|
||||
## Copyright (C) 2005 Travis Shirk <travis@pobox.com>
|
||||
##
|
||||
## 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()
|
||||
|
|
|
@ -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 = '<span %s>%s</span>' % (font_attrs, self.room_jid)
|
||||
|
@ -672,8 +675,6 @@ class GroupchatControl(ChatControlBase):
|
|||
text += '\n<span %s>%s</span>' % (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, '<b>%s</b>' % role_name, None))
|
||||
iter = model.append(role_iter, (None, 'contact', nick, name, None))
|
||||
(gajim.interface.roster.jabber_state_images['16']['closed'], role,
|
||||
'role', '<b>%s</b>' % 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)
|
||||
|
|
|
@ -22,6 +22,7 @@ import threading
|
|||
|
||||
import gtk
|
||||
import pango
|
||||
from common import i18n
|
||||
import dialogs
|
||||
|
||||
from cStringIO import StringIO
|
||||
|
|
|
@ -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'''
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
#!/bin/sh
|
||||
''':'
|
||||
exec python -OOt "$0" ${1+"$@"}
|
||||
' '''
|
||||
#!/usr/bin/env python
|
||||
## history_manager.py
|
||||
##
|
||||
## Copyright (C) 2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
|
@ -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 = '<span foreground="%s">%s</span>' % (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_ = '<span'
|
||||
if color:
|
||||
message_ += ' foreground="%s"' % color
|
||||
message_ += '>%s</span>' % \
|
||||
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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
## rst_xhtml_generator.py
|
||||
##
|
||||
## Copyright (C) 2006 Yann Le Boulanger <asterix@lagaule.org>
|
||||
## Copyright (C) 2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
## 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_
|
||||
''')
|
69
src/statusicon.py
Normal file
69
src/statusicon.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
## statusicon.py
|
||||
##
|
||||
## Copyright (C) 2006 Nikos Kouremenos <kourem@gmail.com>
|
||||
##
|
||||
## 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())
|
|
@ -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)
|
||||
|
|
129
src/tooltips.py
129
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 += ' - <i>' + status + '</i>'
|
||||
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 = '<b>' + \
|
||||
gtkgui_helpers.escape_for_pango_markup(contact.get_shown_name()) \
|
||||
+ '</b>'
|
||||
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 = '<i>' +\
|
||||
gtkgui_helpers.escape_for_pango_markup(status) + '</i>'
|
||||
properties.append((status, None))
|
||||
else: # no status message, show SHOW instead
|
||||
show = helpers.get_uf_show(contact.show)
|
||||
show = '<i>' + show + '</i>'
|
||||
properties.append((show, None))
|
||||
|
||||
if contact.jid.strip() != '':
|
||||
jid_markup = '<span weight="bold">' + contact.jid + '</span>'
|
||||
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
|
||||
|
|
57
src/vcard.py
57
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() +
|
||||
'</span></b>')
|
||||
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()
|
||||
|
|
Loading…
Add table
Reference in a new issue