merge from trunk

This commit is contained in:
Dimitur Kirov 2006-09-26 15:57:47 +00:00
parent d4663922c7
commit 5fc8cf20f3
37 changed files with 2791 additions and 1129 deletions

View file

@ -1,14 +1,38 @@
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) Gajim 0.10.1 (06 June 2006)
* freeze and lost contacts in roster (#1953) * Freeze and lost contacts in roster (#1953)
* popup menus are correctly placed * Popup menus are correctly placed
* high CPU usage on FreeBSD (#1963) * High CPU usage on FreeBSD (#1963)
* nickname can contain '|' (#1913) * Nickname can contain '|' (#1913)
* update pl, cs, fr translations * Update pl, cs, fr translations
* don't play sound, when no event is shown (#1970) * Don't play sound, when no event is shown (#1970)
* set gajim icon for history manager * Set gajim icon for history manager
* gajim.desktop is generated with translation (#834) * gajim.desktop is generated with translation (#834)
* preventing several TBs and annoyances (r6273, r6275, r6279, r6301, * Preventing several TBs and annoyances (r6273, r6275, r6279, r6301,
r6308, r6311, r6323, r6326, r6327, r6335, r6342, r6346, r6348) r6308, r6311, r6323, r6326, r6327, r6335, r6342, r6346, r6348)
Gajim 0.10 (01 May 2006) Gajim 0.10 (01 May 2006)

16
README
View file

@ -1,10 +1,10 @@
Welcome and thanks for trying out Gajim. Welcome and thanks for trying out Gajim.
=RUNTIME REQUIREMENTS= =RUNTIME REQUIREMENTS=
python2.4 (python2.3 should work too) python2.4 or higher
pygtk2.6 or higher pygtk2.6 or higher
python-libglade python-libglade
pysqlite2 (aka. python-pysqlite2) pysqlite2 (if you have python 2.5, you already have this)
some distros also split too much python standard library. some distros also split too much python standard library.
I know SUSE does. In such distros you also need python-xml I know SUSE does. In such distros you also need python-xml
@ -29,7 +29,8 @@ notification-daemon (and D-Bus) to get cooler popups
D-Bus to have gajim-remote working D-Bus to have gajim-remote working
NOTE TO PACKAGERS: NOTE TO PACKAGERS:
Gajim is a GTK+ app and not a gnome one. Just do 'make' so you don't require gnomepythonextras Gajim is a GTK+ app and not a gnome one.
Just do 'make' so you don't require gnomepythonextras
which is gnome dep which is gnome dep
=INSTALLATION PROCEDURE= =INSTALLATION PROCEDURE=
@ -65,9 +66,6 @@ you're advised to enable verbose via advanced configuration window.
If you don't want to make this permanent, execute gajim with --verbose If you don't want to make this permanent, execute gajim with --verbose
everytime you want to have verbose output. everytime you want to have verbose output.
Cannot join room with password:
please read the FAQ for the reply on this issue
=FAQ/Wiki= =FAQ/Wiki=
FAQ can be found at http://trac.gajim.org/wiki/GajimFaq FAQ can be found at http://trac.gajim.org/wiki/GajimFaq
Wiki can be found at http://trac.gajim.org/wiki Wiki can be found at http://trac.gajim.org/wiki
@ -75,13 +73,13 @@ Wiki can be found at http://trac.gajim.org/wiki
That is all, enjoy! That is all, enjoy!
(C) 2003-2005 (C) 2003-2006
The Gajim Team The Gajim Team
http://gajim.org http://gajim.org
PS. PS.
we use original art and parts of sounds and other art from Psi, Gossip, We use original art and parts of sounds and other art from Psi, Gossip,
Gnomebaker, Gaim and some icons from various gnome-icons Gnomebaker, Gaim and some icons from various gnome-icons
(mostly Dropline Etiquette) we found at art.gnome.org (mostly Dropline Etiquette) we found at art.gnome.org
If you think we're violating a license please inform us If you think we're violating a license please inform us. Thank you

View file

@ -554,52 +554,6 @@ Banner</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkLabel" id="label388">
<property name="visible">True</property>
<property name="label" translatable="yes">Active</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">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="active_colorbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="use_alpha">False</property>
<property name="focus_on_click">True</property>
<signal name="color_set" handler="on_active_colorbutton_color_set" last_modification_time="Sat, 18 Mar 2006 22:34:13 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child> <child>
<widget class="GtkLabel" id="label393"> <widget class="GtkLabel" id="label393">
<property name="visible">True</property> <property name="visible">True</property>

View file

@ -374,7 +374,7 @@ Status message</property>
<child> <child>
<widget class="GtkImage" id="image1338"> <widget class="GtkImage" id="image1338">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-preferences</property> <property name="stock">gtk-execute</property>
<property name="icon_size">4</property> <property name="icon_size">4</property>
<property name="xalign">0.5</property> <property name="xalign">0.5</property>
<property name="yalign">0.5</property> <property name="yalign">0.5</property>
@ -916,7 +916,7 @@ topic</property>
<child> <child>
<widget class="GtkImage" id="image1344"> <widget class="GtkImage" id="image1344">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-preferences</property> <property name="stock">gtk-execute</property>
<property name="icon_size">4</property> <property name="icon_size">4</property>
<property name="xalign">0.5</property> <property name="xalign">0.5</property>
<property name="yalign">0.5</property> <property name="yalign">0.5</property>

View file

@ -819,7 +819,7 @@ Per type</property>
<property name="yalign">0.5</property> <property name="yalign">0.5</property>
<property name="xpad">0</property> <property name="xpad">0</property>
<property name="ypad">0</property> <property name="ypad">0</property>
<property name="mnemonic_widget">before_time_entry</property> <property name="mnemonic_widget">scrolledwindow25</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property> <property name="width_chars">-1</property>
<property name="single_line_mode">False</property> <property name="single_line_mode">False</property>
@ -848,7 +848,7 @@ Per type</property>
<property name="yalign">0.5</property> <property name="yalign">0.5</property>
<property name="xpad">0</property> <property name="xpad">0</property>
<property name="ypad">0</property> <property name="ypad">0</property>
<property name="mnemonic_widget">after_nickname_entry</property> <property name="mnemonic_widget">scrolledwindow28</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property> <property name="width_chars">-1</property>
<property name="single_line_mode">False</property> <property name="single_line_mode">False</property>
@ -998,7 +998,7 @@ Per type</property>
<property name="yalign">0.5</property> <property name="yalign">0.5</property>
<property name="xpad">0</property> <property name="xpad">0</property>
<property name="ypad">0</property> <property name="ypad">0</property>
<property name="mnemonic_widget">after_time_entry</property> <property name="mnemonic_widget">scrolledwindow26</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property> <property name="width_chars">-1</property>
<property name="single_line_mode">False</property> <property name="single_line_mode">False</property>
@ -1027,7 +1027,7 @@ Per type</property>
<property name="yalign">0.5</property> <property name="yalign">0.5</property>
<property name="xpad">0</property> <property name="xpad">0</property>
<property name="ypad">0</property> <property name="ypad">0</property>
<property name="mnemonic_widget">before_nickname_entry</property> <property name="mnemonic_widget">scrolledwindow27</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property> <property name="width_chars">-1</property>
<property name="single_line_mode">False</property> <property name="single_line_mode">False</property>
@ -1043,54 +1043,6 @@ Per type</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkEntry" id="after_time_entry">
<property name="width_request">39</property>
<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">False</property>
<signal name="focus_out_event" handler="on_after_time_entry_focus_out_event" last_modification_time="Fri, 01 Apr 2005 15:57:17 GMT"/>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options"></property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="after_nickname_entry">
<property name="width_request">40</property>
<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">False</property>
<signal name="focus_out_event" handler="on_after_nickname_entry_focus_out_event" last_modification_time="Fri, 01 Apr 2005 15:58:07 GMT"/>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
<property name="y_options"></property>
</packing>
</child>
<child> <child>
<widget class="GtkColorButton" id="incoming_msg_colorbutton"> <widget class="GtkColorButton" id="incoming_msg_colorbutton">
<property name="visible">True</property> <property name="visible">True</property>
@ -1132,54 +1084,6 @@ Per type</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkEntry" id="before_nickname_entry">
<property name="width_request">40</property>
<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">False</property>
<signal name="focus_out_event" handler="on_before_nickname_entry_focus_out_event" last_modification_time="Fri, 01 Apr 2005 15:57:44 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="before_time_entry">
<property name="width_request">40</property>
<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">False</property>
<signal name="focus_out_event" handler="on_before_time_entry_focus_out_event" last_modification_time="Fri, 01 Apr 2005 15:54:51 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options"></property>
<property name="y_options"></property>
</packing>
</child>
<child> <child>
<widget class="GtkHBox" id="hbox3022"> <widget class="GtkHBox" id="hbox3022">
<property name="visible">True</property> <property name="visible">True</property>
@ -1298,6 +1202,170 @@ Per type</property>
<property name="x_options">fill</property> <property name="x_options">fill</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow26">
<property name="height_request">30</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="after_time_textview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_CHAR</property>
<property name="cursor_visible">True</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
<signal name="focus_out_event" handler="on_after_time_textview_focus_out_event" last_modification_time="Wed, 20 Sep 2006 19:52:22 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow28">
<property name="height_request">30</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="after_nickname_textview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_CHAR</property>
<property name="cursor_visible">True</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
<signal name="focus_out_event" handler="on_after_nickname_textview_focus_out_event" last_modification_time="Wed, 20 Sep 2006 19:52:51 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow27">
<property name="height_request">30</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="before_nickname_textview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_CHAR</property>
<property name="cursor_visible">True</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
<signal name="focus_out_event" handler="on_before_nickname_textview_focus_out_event" last_modification_time="Wed, 20 Sep 2006 19:52:05 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow25">
<property name="height_request">30</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="before_time_textview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_CHAR</property>
<property name="cursor_visible">True</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
<signal name="focus_out_event" handler="on_before_time_textview_focus_out_event" last_modification_time="Wed, 20 Sep 2006 18:21:39 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>
@ -2543,6 +2611,26 @@ Disabled</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkCheckButton" id="set_status_msg_from_current_music_track_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Set status message to reflect currently playing _music track</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="set_status_msg_from_current_music_track_checkbutton_toggled" last_modification_time="Fri, 22 Sep 2006 18:13:39 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child> <child>
<widget class="GtkEventBox" id="eventbox6"> <widget class="GtkEventBox" id="eventbox6">
<property name="visible">True</property> <property name="visible">True</property>

View file

@ -0,0 +1,779 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="privacy_list_edit_window">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="title" translatable="yes">Privacy List</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">False</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<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_privacy_list_edit_window_destroy" last_modification_time="Sun, 02 Jul 2006 22:34:41 GMT"/>
<child>
<widget class="GtkVBox" id="main_vbox">
<property name="width_request">600</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHBox" id="title_hbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkLabel" id="privacy_lists_title_label">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;i&gt;Privacy List&lt;/i&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</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="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="privacy_list_active_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Active for this session</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_privacy_list_active_checkbutton_toggled" last_modification_time="Sat, 01 Jul 2006 13:09:51 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="privacy_list_default_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Active on each startup</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_privacy_list_default_checkbutton_toggled" last_modification_time="Sat, 01 Jul 2006 13:10:00 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="title_hseparator">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="list_of_rules_label">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;List of rules&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</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="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="list_of_rules_combobox">
<property name="visible">True</property>
<property name="items" translatable="yes"></property>
<property name="add_tearoffs">False</property>
<property name="focus_on_click">True</property>
<signal name="changed" handler="on_list_of_rules_combobox_changed" last_modification_time="Mon, 03 Jul 2006 20:44:19 GMT"/>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="delete_open_buttons_hbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="new_rule_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-add</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_new_rule_button_clicked" last_modification_time="Sat, 01 Jul 2006 13:09:03 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="delete_rule_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-remove</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_delete_rule_button_clicked" last_modification_time="Sat, 01 Jul 2006 13:08:57 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="open_rule_button">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-edit</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_open_rule_button_clicked" last_modification_time="Sat, 01 Jul 2006 13:08:50 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="add_edit_vbox">
<property name="border_width">5</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHSeparator" id="edit_between_list_edit_hseparator">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="add_edit_rule_label">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Add / Edit a rule&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</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="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="edit_fields_hbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkVBox" id="edit_allow_deny_vbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkRadioButton" id="edit_allow_radiobutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Allow</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkRadioButton" id="edit_deny_radiobutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Deny</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">edit_allow_radiobutton</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="edit_type_vbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHBox" id="edit_type_jabberid_hbox">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkRadioButton" id="edit_type_jabberid_radiobutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">JabberID</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="edit_type_jabberid_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">False</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="edit_type_group_hbox">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkRadioButton" id="edit_type_group_radiobutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">all in the group</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">edit_type_jabberid_radiobutton</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="edit_type_group_combobox">
<property name="visible">True</property>
<property name="items" translatable="yes"></property>
<property name="add_tearoffs">False</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="edit_type_subscription_hbox">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkRadioButton" id="edit_type_subscription_radiobutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">all by subscription</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">edit_type_jabberid_radiobutton</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="edit_type_subscription_combobox">
<property name="visible">True</property>
<property name="items" translatable="yes">none
both
from
to</property>
<property name="add_tearoffs">False</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="edit_type_select_all_hbox">
<property name="border_width">10</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkRadioButton" id="edit_type_select_all_radiobutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">All</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">edit_type_jabberid_radiobutton</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="edit_items_vbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkCheckButton" id="edit_send_messages_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">to send me messages</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="edit_queries_send_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">to send me queries</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="edit_send_status_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">to view my status</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="edit_view_status_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">to send me status</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="edit_order_new_save_buttons_hbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHBox" id="edit_order_hbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkLabel" id="edit_order_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Order:</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.5</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="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkSpinButton" id="edit_order_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="climb_rate">1</property>
<property name="digits">0</property>
<property name="numeric">False</property>
<property name="update_policy">GTK_UPDATE_ALWAYS</property>
<property name="snap_to_ticks">False</property>
<property name="wrap">False</property>
<property name="adjustment">1 0 100 1 10 10</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="save_rule_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-save</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_save_rule_button_clicked" last_modification_time="Sat, 01 Jul 2006 13:08:40 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="edit_last_buttons_separator">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="last_buttons_hbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="privacy_list_refresh_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-refresh</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_privacy_list_refresh_button_clicked" last_modification_time="Sat, 01 Jul 2006 13:09:35 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="privacy_list_close_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_privacy_list_close_button_clicked" last_modification_time="Sat, 01 Jul 2006 13:09:28 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View file

@ -0,0 +1,255 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="privacy_lists_first_window">
<property name="border_width">12</property>
<property name="visible">True</property>
<property name="title" translatable="yes">window1</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<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_privacy_lists_first_window_destroy" last_modification_time="Sun, 02 Jul 2006 20:56:21 GMT"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkLabel" id="Server-based_privacy_lists_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Server-based Privacy Lists</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.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">5</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="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="list_of_privacy_lists_combobox">
<property name="border_width">4</property>
<property name="visible">True</property>
<property name="items" translatable="yes"></property>
<property name="add_tearoffs">False</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="buttons_hbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="delete_privacy_list_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-delete</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_delete_privacy_list_button_clicked" last_modification_time="Sun, 02 Jul 2006 16:47:54 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="open_privacy_list_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-open</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_open_privacy_list_button_clicked" last_modification_time="Sun, 02 Jul 2006 16:47:34 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="create_privacy_list_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Create your own Privacy Lists</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.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">5</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="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="new_privacy_list_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">False</property>
</widget>
<packing>
<property name="padding">4</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="new_privacy_list_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-new</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_new_privacy_list_button_clicked" last_modification_time="Sun, 02 Jul 2006 16:47:16 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator2">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="privacy_lists_refresh_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-refresh</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_privacy_lists_refresh_button_clicked" last_modification_time="Sun, 02 Jul 2006 16:46:48 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="close_privacy_lists_window_button">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_close_button_clicked" last_modification_time="Sun, 02 Jul 2006 20:53:03 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View file

@ -4,7 +4,6 @@
<glade-interface> <glade-interface>
<widget class="GtkWindow" id="profile_window"> <widget class="GtkWindow" id="profile_window">
<property name="border_width">12</property>
<property name="title">Personal Information</property> <property name="title">Personal Information</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property> <property name="window_position">GTK_WIN_POS_NONE</property>
@ -29,6 +28,7 @@
<child> <child>
<widget class="GtkNotebook" id="information_notebook"> <widget class="GtkNotebook" id="information_notebook">
<property name="border_width">6</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="show_tabs">True</property> <property name="show_tabs">True</property>
<property name="show_border">True</property> <property name="show_border">True</property>
@ -1016,7 +1016,7 @@
</child> </child>
</widget> </widget>
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">1</property>
<property name="right_attach">4</property> <property name="right_attach">4</property>
<property name="top_attach">6</property> <property name="top_attach">6</property>
<property name="bottom_attach">7</property> <property name="bottom_attach">7</property>
@ -1024,6 +1024,34 @@
<property name="y_options">expand</property> <property name="y_options">expand</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkLabel" id="label58">
<property name="visible">True</property>
<property name="label" translatable="yes">Avatar:</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">6</property>
<property name="bottom_attach">7</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget> </widget>
<packing> <packing>
<property name="tab_expand">False</property> <property name="tab_expand">False</property>
@ -1799,6 +1827,28 @@
</packing> </packing>
</child> </child>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkProgressBar" id="progressbar">
<property name="visible">True</property>
<property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property>
<property name="fraction">0</property>
<property name="pulse_step">0.10000000149</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child> <child>
<widget class="GtkHButtonBox" id="information_hbuttonbox"> <widget class="GtkHButtonBox" id="information_hbuttonbox">
<property name="visible">True</property> <property name="visible">True</property>
@ -1954,6 +2004,26 @@
</child> </child>
</widget> </widget>
</child> </child>
<child>
<widget class="GtkButton" id="close_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_close_button_clicked" last_modification_time="Mon, 25 Sep 2006 04:58:43 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>
@ -1961,6 +2031,18 @@
<property name="fill">True</property> <property name="fill">True</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkStatusbar" id="statusbar">
<property name="visible">True</property>
<property name="has_resize_grip">False</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget> </widget>
</child> </child>
</widget> </widget>

View file

@ -1,141 +1,182 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> <!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<!-- Generated with glade3
Version: 3.0.0
Date: Fri Aug 18 19:07:58 2006
User: kirov
Host: kirov
-->
<glade-interface> <glade-interface>
<widget class="GtkWindow" id="roster_window"> <widget class="GtkWindow" id="roster_window">
<property name="width_request">85</property> <property name="width_request">85</property>
<property name="height_request">200</property> <property name="height_request">200</property>
<property name="title">Gajim</property> <property name="title" translatable="yes">Gajim</property>
<property name="role">roster</property> <property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="default_width">150</property> <property name="default_width">150</property>
<property name="default_height">400</property> <property name="default_height">400</property>
<signal name="focus_out_event" handler="on_roster_window_focus_out_event"/> <property name="resizable">True</property>
<signal name="focus_in_event" handler="on_roster_window_focus_in_event"/> <property name="destroy_with_parent">False</property>
<signal name="key_press_event" handler="on_roster_window_key_press_event"/> <property name="role">roster</property>
<signal name="delete_event" handler="on_roster_window_delete_event"/> <property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<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="delete_event" handler="on_roster_window_delete_event" last_modification_time="Mon, 21 Mar 2005 12:34:59 GMT"/>
<signal name="focus_in_event" handler="on_roster_window_focus_in_event" last_modification_time="Sun, 04 Sep 2005 16:33:35 GMT"/>
<signal name="key_press_event" handler="on_roster_window_key_press_event" last_modification_time="Tue, 20 Sep 2005 19:26:27 GMT"/>
<signal name="focus_out_event" handler="on_roster_window_focus_out_event" last_modification_time="Tue, 08 Nov 2005 14:01:01 GMT"/>
<child> <child>
<widget class="GtkVBox" id="roster_vbox"> <widget class="GtkVBox" id="roster_vbox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child> <child>
<widget class="GtkMenuBar" id="menubar"> <widget class="GtkMenuBar" id="menubar">
<property name="visible">True</property> <property name="visible">True</property>
<property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
<property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
<child> <child>
<widget class="GtkMenuItem" id="actions_menu"> <widget class="GtkMenuItem" id="actions_menu">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Actions</property> <property name="label" translatable="yes">_Actions</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_actions_menuitem_activate"/> <signal name="activate" handler="on_actions_menuitem_activate" last_modification_time="Sun, 19 Feb 2006 17:10:56 GMT"/>
<child> <child>
<widget class="GtkMenu" id="actions_menu_menu"> <widget class="GtkMenu" id="actions_menu_menu">
<child> <child>
<widget class="GtkImageMenuItem" id="new_chat_menuitem"> <widget class="GtkImageMenuItem" id="new_chat_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Start Chat</property> <property name="label" translatable="yes">_Start Chat</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1444"> <widget class="GtkImage" id="image1444">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-jump-to</property> <property name="stock">gtk-jump-to</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="join_gc_menuitem"> <widget class="GtkImageMenuItem" id="join_gc_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Group Chat</property> <property name="label" translatable="yes">_Group Chat</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1445"> <widget class="GtkImage" id="image1445">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-connect</property> <property name="stock">gtk-connect</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1"> <widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property> <property name="visible">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="add_new_contact_menuitem"> <widget class="GtkImageMenuItem" id="add_new_contact_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">Add _Contact</property> <property name="label" translatable="yes">Add _Contact</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1446"> <widget class="GtkImage" id="image1446">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-add</property> <property name="stock">gtk-add</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="service_disco_menuitem"> <widget class="GtkImageMenuItem" id="service_disco_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Discover Services</property> <property name="label" translatable="yes">_Discover Services</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1447"> <widget class="GtkImage" id="image1447">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-find</property> <property name="stock">gtk-find</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkMenuItem" id="advanced_menuitem"> <widget class="GtkMenuItem" id="advanced_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Advanced</property> <property name="label" translatable="yes">_Advanced</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkCheckMenuItem" id="show_offline_contacts_menuitem"> <widget class="GtkCheckMenuItem" id="show_offline_contacts_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">Show _Offline Contacts</property> <property name="label" translatable="yes">Show _Offline Contacts</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_show_offline_contacts_menuitem_activate"/> <property name="active">False</property>
<signal name="activate" handler="on_show_offline_contacts_menuitem_activate" last_modification_time="Tue, 01 Mar 2005 23:29:52 GMT"/>
<accelerator key="O" modifiers="GDK_CONTROL_MASK" signal="activate"/> <accelerator key="O" modifiers="GDK_CONTROL_MASK" signal="activate"/>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkSeparatorMenuItem" id="separator1"> <widget class="GtkSeparatorMenuItem" id="separator1">
<property name="visible">True</property> <property name="visible">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="quit_menuitem"> <widget class="GtkImageMenuItem" id="quit_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Quit</property> <property name="label" translatable="yes">_Quit</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_quit_menuitem_activate"/> <signal name="activate" handler="on_quit_menuitem_activate" last_modification_time="Tue, 01 Mar 2005 23:37:49 GMT"/>
<accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/> <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1448"> <widget class="GtkImage" id="image1448">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-quit</property> <property name="stock">gtk-quit</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
@ -144,84 +185,104 @@
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkMenuItem" id="edit_menu"> <widget class="GtkMenuItem" id="edit_menu">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Edit</property> <property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_edit_menuitem_activate"/> <signal name="activate" handler="on_edit_menuitem_activate" last_modification_time="Fri, 07 Apr 2006 22:46:56 GMT"/>
<child> <child>
<widget class="GtkMenu" id="edit_menu_menu"> <widget class="GtkMenu" id="edit_menu_menu">
<child> <child>
<widget class="GtkImageMenuItem" id="accounts_menuitem"> <widget class="GtkImageMenuItem" id="accounts_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">A_ccounts</property> <property name="label" translatable="yes">A_ccounts</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_accounts_menuitem_activate"/> <signal name="activate" handler="on_accounts_menuitem_activate" last_modification_time="Tue, 01 Mar 2005 23:23:19 GMT"/>
<accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/> <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1449"> <widget class="GtkImage" id="image1449">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-network</property> <property name="stock">gtk-network</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="file_transfers_menuitem"> <widget class="GtkImageMenuItem" id="file_transfers_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">File _Transfers</property> <property name="label" translatable="yes">File _Transfers</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_file_transfers_menuitem_activate"/> <signal name="activate" handler="on_file_transfers_menuitem_activate" last_modification_time="Wed, 03 Aug 2005 15:44:28 GMT"/>
<accelerator key="T" modifiers="GDK_CONTROL_MASK" signal="activate"/> <accelerator key="T" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1450"> <widget class="GtkImage" id="image1450">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property> <property name="stock">gtk-file</property>
<property name="yalign">0,000000</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="profile_avatar_menuitem"> <widget class="GtkImageMenuItem" id="profile_avatar_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">Profile, Avatar</property> <property name="label" translatable="yes">Profile, Avatar</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1305"> <widget class="GtkImage" id="image1305">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-properties</property> <property name="stock">gtk-properties</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkSeparatorMenuItem" id="separator2"> <widget class="GtkSeparatorMenuItem" id="separator2">
<property name="visible">True</property> <property name="visible">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="preferences_menuitem"> <widget class="GtkImageMenuItem" id="preferences_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Preferences</property> <property name="label" translatable="yes">_Preferences</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_preferences_menuitem_activate"/> <signal name="activate" handler="on_preferences_menuitem_activate" last_modification_time="Tue, 01 Mar 2005 22:58:18 GMT"/>
<accelerator key="P" modifiers="GDK_CONTROL_MASK" signal="activate"/> <accelerator key="P" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1451"> <widget class="GtkImage" id="image1451">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-preferences</property> <property name="stock">gtk-preferences</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
@ -230,47 +291,54 @@
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkMenuItem" id="help_menu"> <widget class="GtkMenuItem" id="help_menu">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">_Help</property> <property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child> <child>
<widget class="GtkMenu" id="help_menu_menu"> <widget class="GtkMenu" id="help_menu_menu">
<child> <child>
<widget class="GtkImageMenuItem" id="contents_menuitem"> <widget class="GtkImageMenuItem" id="contents_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip">Help online</property> <property name="tooltip" translatable="yes">Help online</property>
<property name="label">_Contents</property> <property name="label" translatable="yes">_Contents</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_contents_menuitem_activate"/> <signal name="activate" handler="on_contents_menuitem_activate" last_modification_time="Thu, 06 Oct 2005 23:29:10 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1452"> <widget class="GtkImage" id="image1452">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0,000000</property>
<property name="yalign">0,000000</property>
<property name="stock">gtk-help</property> <property name="stock">gtk-help</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkMenuItem" id="faq_menuitem"> <widget class="GtkMenuItem" id="faq_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip">Frequently Asked Questions (online)</property> <property name="tooltip" translatable="yes">Frequently Asked Questions (online)</property>
<property name="label">_FAQ</property> <property name="label" translatable="yes">_FAQ</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_faq_menuitem_activate"/> <signal name="activate" handler="on_faq_menuitem_activate" last_modification_time="Thu, 06 Oct 2005 23:29:10 GMT"/>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="about_menuitem"> <widget class="GtkImageMenuItem" id="about_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">gtk-about</property> <property name="label">gtk-about</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
<signal name="activate" handler="on_about_menuitem_activate"/> <signal name="activate" handler="on_about_menuitem_activate" last_modification_time="Tue, 01 Mar 2005 22:56:45 GMT"/>
</widget> </widget>
</child> </child>
</widget> </widget>
@ -279,50 +347,67 @@
</child> </child>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
</packing> </packing>
</child> </child>
<child> <child>
<widget class="GtkScrolledWindow" id="scrolledwindow"> <widget class="GtkScrolledWindow" id="scrolledwindow">
<property name="border_width">2</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="border_width">2</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child> <child>
<widget class="GtkTreeView" id="roster_treeview"> <widget class="GtkTreeView" id="roster_treeview">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="headers_visible">False</property> <property name="headers_visible">False</property>
<property name="rules_hint">False</property>
<property name="reorderable">True</property> <property name="reorderable">True</property>
<signal name="leave_notify_event" handler="on_roster_treeview_leave_notify_event"/> <property name="enable_search">True</property>
<signal name="button_press_event" handler="on_roster_treeview_button_press_event"/> <property name="fixed_height_mode">False</property>
<signal name="motion_notify_event" handler="on_roster_treeview_motion_notify_event"/> <property name="hover_selection">False</property>
<signal name="row_collapsed" handler="on_roster_treeview_row_collapsed"/> <property name="hover_expand">False</property>
<signal name="row_expanded" handler="on_roster_treeview_row_expanded"/> <signal name="button_press_event" handler="on_roster_treeview_button_press_event" last_modification_time="Mon, 28 Feb 2005 14:16:44 GMT"/>
<signal name="key_press_event" handler="on_roster_treeview_key_press_event"/> <signal name="row_activated" handler="on_roster_treeview_row_activated" last_modification_time="Mon, 28 Feb 2005 14:18:06 GMT"/>
<signal name="row_activated" handler="on_roster_treeview_row_activated"/> <signal name="row_expanded" handler="on_roster_treeview_row_expanded" last_modification_time="Mon, 28 Feb 2005 14:18:14 GMT"/>
<signal name="scroll_event" handler="on_roster_treeview_scroll_event"/> <signal name="row_collapsed" handler="on_roster_treeview_row_collapsed" last_modification_time="Mon, 28 Feb 2005 14:18:33 GMT"/>
<signal name="style_set" handler="on_roster_treeview_style_set"/> <signal name="key_press_event" handler="on_roster_treeview_key_press_event" last_modification_time="Sat, 26 Mar 2005 20:39:36 GMT"/>
<signal name="motion_notify_event" handler="on_roster_treeview_motion_notify_event" last_modification_time="Wed, 06 Jul 2005 14:38:58 GMT"/>
<signal name="leave_notify_event" handler="on_roster_treeview_leave_notify_event" last_modification_time="Wed, 06 Jul 2005 14:39:06 GMT"/>
<signal name="scroll_event" handler="on_roster_treeview_scroll_event" last_modification_time="Fri, 08 Jul 2005 22:09:03 GMT"/>
<signal name="style_set" handler="on_roster_treeview_style_set" last_modification_time="Tue, 08 Nov 2005 14:03:30 GMT"/>
</widget> </widget>
</child> </child>
</widget> </widget>
<packing> <packing>
<property name="position">1</property> <property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing> </packing>
</child> </child>
<child> <child>
<widget class="GtkComboBox" id="status_combobox"> <widget class="GtkComboBox" id="status_combobox">
<property name="visible">True</property> <property name="visible">True</property>
<signal name="changed" handler="on_status_combobox_changed"/> <property name="add_tearoffs">False</property>
<property name="focus_on_click">True</property>
<signal name="changed" handler="on_status_combobox_changed" last_modification_time="Sat, 05 Nov 2005 18:07:49 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property>
<property name="expand">False</property> <property name="expand">False</property>
<property name="position">2</property> <property name="fill">True</property>
</packing> </packing>
</child> </child>
</widget> </widget>
</child> </child>
</widget> </widget>
</glade-interface> </glade-interface>

View file

@ -2,6 +2,7 @@
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> <!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface> <glade-interface>
<widget class="GtkMenu" id="systray_context_menu"> <widget class="GtkMenu" id="systray_context_menu">
<child> <child>
@ -11,7 +12,7 @@
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1371"> <widget class="GtkImage" id="image1455">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-network</property> <property name="stock">gtk-network</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
@ -31,7 +32,7 @@
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1372"> <widget class="GtkImage" id="image1456">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-jump-to</property> <property name="stock">gtk-jump-to</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
@ -51,7 +52,7 @@
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1445"> <widget class="GtkImage" id="image1457">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-connect</property> <property name="stock">gtk-connect</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
@ -71,7 +72,7 @@
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1373"> <widget class="GtkImage" id="image1458">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-new</property> <property name="stock">gtk-new</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
@ -107,7 +108,7 @@
<signal name="activate" handler="on_show_roster_menuitem_activate" last_modification_time="Sat, 29 Oct 2005 23:55:24 GMT"/> <signal name="activate" handler="on_show_roster_menuitem_activate" last_modification_time="Sat, 29 Oct 2005 23:55:24 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1374"> <widget class="GtkImage" id="image1459">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-home</property> <property name="stock">gtk-home</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
@ -144,4 +145,5 @@
</widget> </widget>
</child> </child>
</widget> </widget>
</glade-interface> </glade-interface>

View file

@ -652,7 +652,7 @@
</child> </child>
<child> <child>
<widget class="GtkTable" id="table2"> <widget class="GtkTable" id="personal_info_table">
<property name="border_width">12</property> <property name="border_width">12</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="n_rows">6</property> <property name="n_rows">6</property>
@ -1640,34 +1640,6 @@
</packing> </packing>
</child> </child>
<child>
<widget class="GtkLabel" id="URL_label">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes"></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">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xpad">5</property>
<property name="ypad">5</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">1</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child> <child>
<widget class="GtkLabel" id="TEL_HOME_NUMBER_label"> <widget class="GtkLabel" id="TEL_HOME_NUMBER_label">
<property name="visible">True</property> <property name="visible">True</property>
@ -2581,6 +2553,60 @@
<property name="fill">True</property> <property name="fill">True</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkProgressBar" id="progressbar">
<property name="visible">True</property>
<property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property>
<property name="fraction">0</property>
<property name="pulse_step">0.10000000149</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="close_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_close_button_clicked" last_modification_time="Mon, 25 Sep 2006 05:08:55 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget> </widget>
</child> </child>
</widget> </widget>

View file

@ -1334,7 +1334,7 @@ msgstr "W każdej _wiadomości"
#: ../data/glade/preferences_window.glade.h:58 #: ../data/glade/preferences_window.glade.h:58
msgid "One message _window:" msgid "One message _window:"
msgstr "Wyślij wiadomość i _zamknij okno" msgstr "Grupuj okna:"
#: ../data/glade/preferences_window.glade.h:59 #: ../data/glade/preferences_window.glade.h:59
msgid "Play _sounds" msgid "Play _sounds"

View file

@ -196,7 +196,6 @@ class ChatControlBase(MessageControl):
self.msg_textview.lang = lang self.msg_textview.lang = lang
spell.set_language(lang) spell.set_language(lang)
except (gobject.GError, RuntimeError), msg: except (gobject.GError, RuntimeError), msg:
#FIXME: add a ui for this use spell.set_language()
dialogs.ErrorDialog(unicode(msg), _('If that is not your language ' dialogs.ErrorDialog(unicode(msg), _('If that is not your language '
'for which you want to highlight misspelled words, then please ' 'for which you want to highlight misspelled words, then please '
'set your $LANG as appropriate. Eg. for French do export ' 'set your $LANG as appropriate. Eg. for French do export '
@ -1018,7 +1017,7 @@ class ChatControl(ChatControlBase):
acct_info = '' acct_info = ''
self.account_displayed = False self.account_displayed = False
for ctrl in self.parent_win.controls(): for ctrl in self.parent_win.controls():
if ctrl == self: if ctrl == self or ctrl.type_id == 'gc':
continue continue
if self.contact.get_shown_name() == ctrl.contact.get_shown_name()\ if self.contact.get_shown_name() == ctrl.contact.get_shown_name()\
and not avoid_showing_account_too: and not avoid_showing_account_too:
@ -1276,9 +1275,6 @@ class ChatControl(ChatControlBase):
elif chatstate == 'paused': elif chatstate == 'paused':
color = gajim.config.get_per('themes', theme, color = gajim.config.get_per('themes', theme,
'state_paused_color') 'state_paused_color')
else:
color = gajim.config.get_per('themes', theme,
'state_active_color')
if color: if color:
# We set the color for when it's the current tab or not # We set the color for when it's the current tab or not
color = gtk.gdk.colormap_get_system().alloc_color(color) color = gtk.gdk.colormap_get_system().alloc_color(color)
@ -1287,6 +1283,9 @@ class ChatControl(ChatControlBase):
if chatstate in ('inactive', 'gone') and\ if chatstate in ('inactive', 'gone') and\
self.parent_win.get_active_control() != self: self.parent_win.get_active_control() != self:
color = self.lighten_color(color) color = self.lighten_color(color)
elif chatstate == 'active' : # active, get color from gtk
color = self.parent_win.notebook.style.fg[gtk.STATE_ACTIVE]
name = self.contact.get_shown_name() name = self.contact.get_shown_name()
if self.resource: if self.resource:

View file

@ -37,6 +37,8 @@ opt_bool = [ 'boolean', 0 ]
opt_color = [ 'color', '^(#[0-9a-fA-F]{6})|()$' ] opt_color = [ 'color', '^(#[0-9a-fA-F]{6})|()$' ]
opt_one_window_types = ['never', 'always', 'peracct', 'pertype'] opt_one_window_types = ['never', 'always', 'peracct', 'pertype']
DEFAULT_ICONSET = 'dcraven'
class Config: class Config:
__options = { __options = {
@ -67,7 +69,7 @@ class Config:
'last_status_msg_invisible': [ opt_str, '' ], 'last_status_msg_invisible': [ opt_str, '' ],
'last_status_msg_offline': [ opt_str, '' ], 'last_status_msg_offline': [ opt_str, '' ],
'trayicon': [ opt_bool, True, '', True ], 'trayicon': [ opt_bool, True, '', True ],
'iconset': [ opt_str, 'dcraven', '', True ], 'iconset': [ opt_str, DEFAULT_ICONSET, '', True ],
'use_transports_iconsets': [ opt_bool, True, '', True ], 'use_transports_iconsets': [ opt_bool, True, '', True ],
'inmsgcolor': [ opt_color, '#a34526', '', True ], 'inmsgcolor': [ opt_color, '#a34526', '', True ],
'outmsgcolor': [ opt_color, '#164e6f', '', True ], 'outmsgcolor': [ opt_color, '#164e6f', '', True ],
@ -126,6 +128,7 @@ class Config:
'before_nickname': [ opt_str, '' ], 'before_nickname': [ opt_str, '' ],
'after_nickname': [ opt_str, ':' ], 'after_nickname': [ opt_str, ':' ],
'send_os_info': [ opt_bool, True ], 'send_os_info': [ opt_bool, True ],
'set_status_msg_from_current_music_track': [ opt_bool, False ],
'notify_on_new_gmail_email': [ opt_bool, True ], 'notify_on_new_gmail_email': [ opt_bool, True ],
'notify_on_new_gmail_email_extra': [ opt_bool, False ], 'notify_on_new_gmail_email_extra': [ opt_bool, False ],
'usegpg': [ opt_bool, False, '', True ], 'usegpg': [ opt_bool, False, '', True ],
@ -188,7 +191,7 @@ class Config:
'restored_messages_color': [opt_str, 'grey'], 'restored_messages_color': [opt_str, 'grey'],
'restored_messages_small': [opt_bool, True, _('If True, restored messages will use a smaller font than the default one.')], 'restored_messages_small': [opt_bool, True, _('If True, restored messages will use a smaller font than the default one.')],
'hide_avatar_of_transport': [opt_bool, False, _('Don\'t show avatar for the transport itself.')], 'hide_avatar_of_transport': [opt_bool, False, _('Don\'t show avatar for the transport itself.')],
'roster_window_skip_taskbar': [opt_bool, False], 'roster_window_skip_taskbar': [opt_bool, False, _('Don\'t show roster in the system taskbar.')],
'use_urgency_hint': [opt_bool, True, _('If True and installed GTK+ and PyGTK versions are at least 2.8, make the window flash (the default behaviour in most Window Managers) when holding pending events.')], 'use_urgency_hint': [opt_bool, True, _('If True and installed GTK+ and PyGTK versions are at least 2.8, make the window flash (the default behaviour in most Window Managers) when holding pending events.')],
'notification_timeout': [opt_int, 5], 'notification_timeout': [opt_int, 5],
'send_sha_in_gc_presence': [opt_bool, True, _('Jabberd1.4 does not like sha info when one join a password protected room. Turn this option to False to stop sending sha info in group chat presences.')], 'send_sha_in_gc_presence': [opt_bool, True, _('Jabberd1.4 does not like sha info when one join a password protected room. Turn this option to False to stop sending sha info in group chat presences.')],
@ -290,8 +293,6 @@ class Config:
'bannerfontattrs': [ opt_str, 'B', '', True ], 'bannerfontattrs': [ opt_str, 'B', '', True ],
# http://www.pitt.edu/~nisg/cis/web/cgi/rgb.html # http://www.pitt.edu/~nisg/cis/web/cgi/rgb.html
# FIXME: not black but the default color from gtk+ theme
'state_active_color': [ opt_color, 'black' ],
'state_inactive_color': [ opt_color, 'grey62' ], 'state_inactive_color': [ opt_color, 'grey62' ],
'state_composing_color': [ opt_color, 'green4' ], 'state_composing_color': [ opt_color, 'green4' ],
'state_paused_color': [ opt_color, 'mediumblue' ], 'state_paused_color': [ opt_color, 'mediumblue' ],

View file

@ -175,7 +175,7 @@ class ConnectionBytestream:
except socket.gaierror: except socket.gaierror:
self.dispatch('ERROR', (_('Wrong host'), _('The host you configured as the ft_override_host_to_send advanced option is not valid, so ignored.'))) self.dispatch('ERROR', (_('Wrong host'), _('The host you configured as the ft_override_host_to_send advanced option is not valid, so ignored.')))
ft_override_host_to_send = self.peerhost[0] ft_override_host_to_send = self.peerhost[0]
listener = gajim.socks5queue.start_listener(self.peerhost[0], port, listener = gajim.socks5queue.start_listener(port,
sha_str, self._result_socks5_sid, file_props['sid']) sha_str, self._result_socks5_sid, file_props['sid'])
if listener == None: if listener == None:
file_props['error'] = -5 file_props['error'] = -5
@ -1134,6 +1134,12 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco)
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
def _ErrorCB(self, con, iq_obj): def _ErrorCB(self, con, iq_obj):
gajim.log.debug('ErrorCB')
if iq_obj.getQueryNS() == common.xmpp.NS_VERSION:
who = helpers.get_full_jid_from_iq(iq_obj)
jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who)
self.dispatch('OS_INFO', (jid_stripped, resource, '', ''))
return
errmsg = iq_obj.getErrorMsg() errmsg = iq_obj.getErrorMsg()
errcode = iq_obj.getErrorCode() errcode = iq_obj.getErrorCode()
jid_from = helpers.get_full_jid_from_iq(iq_obj) jid_from = helpers.get_full_jid_from_iq(iq_obj)

View file

@ -291,6 +291,21 @@ def get_uf_role(role, plural = False):
role_name = _('Visitor') role_name = _('Visitor')
return role_name return role_name
def get_uf_affiliation(affiliation):
'''Get a nice and translated affilition for muc'''
if affiliation == 'none':
affiliation_name = Q_('?Group Chat Contact Affiliation:None')
elif affiliation == 'owner':
affiliation_name = _('Owner')
elif affiliation == 'admin':
affiliation_name = _('Administrator')
elif affiliation == 'member':
affiliation_name = _('Member')
else: # Argl ! An unknown affiliation !
affiliation_name = affiliation.capitalize()
return affiliation_name
def get_sorted_keys(adict): def get_sorted_keys(adict):
keys = adict.keys() keys = adict.keys()
keys.sort() keys.sort()

View file

@ -74,13 +74,13 @@ class SocksQueue:
self.on_success = None self.on_success = None
self.on_failure = None self.on_failure = None
def start_listener(self, host, port, sha_str, sha_handler, sid): def start_listener(self, port, sha_str, sha_handler, sid):
''' start waiting for incomming connections on (host, port) ''' start waiting for incomming connections on (host, port)
and do a socks5 authentication using sid for generated sha and do a socks5 authentication using sid for generated sha
''' '''
self.sha_handlers[sha_str] = (sha_handler, sid) self.sha_handlers[sha_str] = (sha_handler, sid)
if self.listener == None: if self.listener == None:
self.listener = Socks5Listener(self.idlequeue, host, port) self.listener = Socks5Listener(self.idlequeue, port)
self.listener.queue = self self.listener.queue = self
self.listener.bind() self.listener.bind()
if self.listener.started is False: if self.listener.started is False:
@ -790,12 +790,12 @@ class Socks5Sender(Socks5, IdleObject):
self.queue.remove_sender(self.queue_idx, False) self.queue.remove_sender(self.queue_idx, False)
class Socks5Listener(IdleObject): class Socks5Listener(IdleObject):
def __init__(self, idlequeue, host, port): def __init__(self, idlequeue, port):
''' handle all incomming connections on (host, port) ''' handle all incomming connections on (0.0.0.0, port)
This class implements IdleObject, but we will expect This class implements IdleObject, but we will expect
only pollin events though only pollin events though
''' '''
self.host, self.port = host, port self.port = port
self.queue_idx = -1 self.queue_idx = -1
self.idlequeue = idlequeue self.idlequeue = idlequeue
self.queue = None self.queue = None

View file

@ -19,7 +19,7 @@ Protocol module contains tools that is needed for processing of
xmpp-related data structures. xmpp-related data structures.
""" """
from simplexml import Node,ustr from simplexml import Node,NodeBuilder,ustr
import time import time
NS_ACTIVITY ='http://jabber.org/protocol/activity' # JEP-0108 NS_ACTIVITY ='http://jabber.org/protocol/activity' # JEP-0108
NS_ADDRESS ='http://jabber.org/protocol/address' # JEP-0033 NS_ADDRESS ='http://jabber.org/protocol/address' # JEP-0033
@ -94,6 +94,7 @@ NS_VCARD_UPDATE =NS_VCARD+':x:update'
NS_VERSION ='jabber:iq:version' NS_VERSION ='jabber:iq:version'
NS_WAITINGLIST ='http://jabber.org/protocol/waitinglist' # JEP-0130 NS_WAITINGLIST ='http://jabber.org/protocol/waitinglist' # JEP-0130
NS_XHTML_IM ='http://jabber.org/protocol/xhtml-im' # JEP-0071 NS_XHTML_IM ='http://jabber.org/protocol/xhtml-im' # JEP-0071
NS_XHTML = 'http://www.w3.org/1999/xhtml' # "
NS_DATA_LAYOUT ='http://jabber.org/protocol/xdata-layout' # JEP-0141 NS_DATA_LAYOUT ='http://jabber.org/protocol/xdata-layout' # JEP-0141
NS_DATA_VALIDATE='http://jabber.org/protocol/xdata-validate' # JEP-0122 NS_DATA_VALIDATE='http://jabber.org/protocol/xdata-validate' # JEP-0122
NS_XMPP_STREAMS ='urn:ietf:params:xml:ns:xmpp-streams' NS_XMPP_STREAMS ='urn:ietf:params:xml:ns:xmpp-streams'
@ -385,16 +386,21 @@ class Protocol(Node):
class Message(Protocol): class Message(Protocol):
""" XMPP Message stanza - "push" mechanism.""" """ XMPP Message stanza - "push" mechanism."""
def __init__(self, to=None, body=None, typ=None, subject=None, attrs={}, frm=None, payload=[], timestamp=None, xmlns=NS_CLIENT, node=None): def __init__(self, to=None, body=None, xhtml=None, typ=None, subject=None, attrs={}, frm=None, payload=[], timestamp=None, xmlns=NS_CLIENT, node=None):
""" Create message object. You can specify recipient, text of message, type of message """ Create message object. You can specify recipient, text of message, type of message
any additional attributes, sender of the message, any additional payload (f.e. jabber:x:delay element) and namespace in one go. any additional attributes, sender of the message, any additional payload (f.e. jabber:x:delay element) and namespace in one go.
Alternatively you can pass in the other XML object as the 'node' parameted to replicate it as message. """ Alternatively you can pass in the other XML object as the 'node' parameted to replicate it as message. """
Protocol.__init__(self, 'message', to=to, typ=typ, attrs=attrs, frm=frm, payload=payload, timestamp=timestamp, xmlns=xmlns, node=node) Protocol.__init__(self, 'message', to=to, typ=typ, attrs=attrs, frm=frm, payload=payload, timestamp=timestamp, xmlns=xmlns, node=node)
if body: self.setBody(body) if body: self.setBody(body)
if xhtml: self.setXHTML(xhtml)
if subject: self.setSubject(subject) if subject: self.setSubject(subject)
def getBody(self): def getBody(self):
""" Returns text of the message. """ """ Returns text of the message. """
return self.getTagData('body') return self.getTagData('body')
def getXHTML(self):
""" Returns serialized xhtml-im body text of the message. """
xhtml = self.getTag('html')
return str(xhtml.getTag('body'))
def getSubject(self): def getSubject(self):
""" Returns subject of the message. """ """ Returns subject of the message. """
return self.getTagData('subject') return self.getTagData('subject')
@ -404,6 +410,11 @@ class Message(Protocol):
def setBody(self,val): def setBody(self,val):
""" Sets the text of the message. """ """ Sets the text of the message. """
self.setTagData('body',val) self.setTagData('body',val)
def setXHTML(self,val):
""" Sets the xhtml text of the message (JEP-0071).
The parameter is the "inner html" to the body."""
dom = NodeBuilder(val)
self.setTag('html',namespace=NS_XHTML_IM).setTag('body',namespace=NS_XHTML).addChild(node=dom.getDom())
def setSubject(self,val): def setSubject(self,val):
""" Sets the subject of the message. """ """ Sets the subject of the message. """
self.setTagData('subject',val) self.setTagData('subject',val)

View file

@ -1,7 +1,7 @@
## config.py ## config.py
## ##
## Copyright (C) 2003-2006 Yann Le Boulanger <asterix@lagaule.org> ## Copyright (C) 2003-2006 Yann Le Boulanger <asterix@lagaule.org>
## Copyright (C) 2005-2006 Nikos Kouremenos <nkour@jabber.org> ## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
## Copyright (C) 2005 Dimitur Kirov <dkirov@gmail.com> ## Copyright (C) 2005 Dimitur Kirov <dkirov@gmail.com>
## Copyright (C) 2003-2005 Vincent Hanquez <tab@snarc.org> ## Copyright (C) 2003-2005 Vincent Hanquez <tab@snarc.org>
## ##
@ -212,19 +212,23 @@ class PreferencesWindow:
#before time #before time
st = gajim.config.get('before_time') st = gajim.config.get('before_time')
self.xml.get_widget('before_time_entry').set_text(st) st = helpers.from_one_line(st)
self.xml.get_widget('before_time_textview').get_buffer().set_text(st)
#after time #after time
st = gajim.config.get('after_time') st = gajim.config.get('after_time')
self.xml.get_widget('after_time_entry').set_text(st) st = helpers.from_one_line(st)
self.xml.get_widget('after_time_textview').get_buffer().set_text(st)
#before nickname #before nickname
st = gajim.config.get('before_nickname') st = gajim.config.get('before_nickname')
self.xml.get_widget('before_nickname_entry').set_text(st) st = helpers.from_one_line(st)
self.xml.get_widget('before_nickname_textview').get_buffer().set_text(st)
#after nickanme #after nickanme
st = gajim.config.get('after_nickname') st = gajim.config.get('after_nickname')
self.xml.get_widget('after_nickname_entry').set_text(st) st = helpers.from_one_line(st)
self.xml.get_widget('after_nickname_textview').get_buffer().set_text(st)
#Color for incomming messages #Color for incomming messages
colSt = gajim.config.get('inmsgcolor') colSt = gajim.config.get('inmsgcolor')
@ -456,11 +460,17 @@ class PreferencesWindow:
st = gajim.config.get('send_os_info') st = gajim.config.get('send_os_info')
self.xml.get_widget('send_os_info_checkbutton').set_active(st) self.xml.get_widget('send_os_info_checkbutton').set_active(st)
# set status msg from currently playing music track
st = gajim.config.get('set_status_msg_from_current_music_track')
self.xml.get_widget(
'set_status_msg_from_current_music_track_checkbutton').set_active(st)
# Notify user of new gmail e-mail messages, # Notify user of new gmail e-mail messages,
# only show checkbox if user has a gtalk account # only show checkbox if user has a gtalk account
frame_gmail = self.xml.get_widget('frame_gmail') frame_gmail = self.xml.get_widget('frame_gmail')
notify_gmail_checkbutton = self.xml.get_widget('notify_gmail_checkbutton') notify_gmail_checkbutton = self.xml.get_widget('notify_gmail_checkbutton')
notify_gmail_extra_checkbutton = self.xml.get_widget('notify_gmail_extra_checkbutton') notify_gmail_extra_checkbutton = self.xml.get_widget(
'notify_gmail_extra_checkbutton')
frame_gmail.set_no_show_all(True) frame_gmail.set_no_show_all(True)
for account in gajim.config.get_per('accounts'): for account in gajim.config.get_per('accounts'):
@ -512,6 +522,8 @@ class PreferencesWindow:
gajim.interface.systray.change_status(show) gajim.interface.systray.change_status(show)
else: else:
gajim.config.set('trayicon', False) gajim.config.set('trayicon', False)
if not gajim.interface.roster.window.get_property('visible'):
gajim.interface.roster.window.present()
gajim.interface.hide_systray() gajim.interface.hide_systray()
gajim.config.set('show_roster_on_startup', True) # no tray, show roster! gajim.config.set('show_roster_on_startup', True) # no tray, show roster!
gajim.interface.roster.draw_roster() gajim.interface.roster.draw_roster()
@ -643,9 +655,9 @@ class PreferencesWindow:
def _set_sensitivity_for_before_after_time_widgets(self, sensitive): def _set_sensitivity_for_before_after_time_widgets(self, sensitive):
self.xml.get_widget('before_time_label').set_sensitive(sensitive) self.xml.get_widget('before_time_label').set_sensitive(sensitive)
self.xml.get_widget('before_time_entry').set_sensitive(sensitive) self.xml.get_widget('before_time_textview').set_sensitive(sensitive)
self.xml.get_widget('after_time_label').set_sensitive(sensitive) self.xml.get_widget('after_time_label').set_sensitive(sensitive)
self.xml.get_widget('after_time_entry').set_sensitive(sensitive) self.xml.get_widget('after_time_textview').set_sensitive(sensitive)
def on_time_never_radiobutton_toggled(self, widget): def on_time_never_radiobutton_toggled(self, widget):
if widget.get_active(): if widget.get_active():
@ -665,20 +677,33 @@ class PreferencesWindow:
self._set_sensitivity_for_before_after_time_widgets(True) self._set_sensitivity_for_before_after_time_widgets(True)
gajim.interface.save_config() gajim.interface.save_config()
def on_before_time_entry_focus_out_event(self, widget, event): def _get_textview_text(self, tv):
gajim.config.set('before_time', widget.get_text().decode('utf-8')) buffer = tv.get_buffer()
begin, end = buffer.get_bounds()
return buffer.get_text(begin, end).decode('utf-8')
def on_before_time_textview_focus_out_event(self, widget, event):
text = self._get_textview_text(widget)
text = helpers.to_one_line(text)
gajim.config.set('before_time', text)
gajim.interface.save_config() gajim.interface.save_config()
def on_after_time_entry_focus_out_event(self, widget, event): def on_after_time_textview_focus_out_event(self, widget, event):
gajim.config.set('after_time', widget.get_text().decode('utf-8')) text = self._get_textview_text(widget)
text = helpers.to_one_line(text)
gajim.config.set('after_time', text)
gajim.interface.save_config() gajim.interface.save_config()
def on_before_nickname_entry_focus_out_event(self, widget, event): def on_before_nickname_textview_focus_out_event(self, widget, event):
gajim.config.set('before_nickname', widget.get_text().decode('utf-8')) text = self._get_textview_text(widget)
text = helpers.to_one_line(text)
gajim.config.set('before_nickname', text)
gajim.interface.save_config() gajim.interface.save_config()
def on_after_nickname_entry_focus_out_event(self, widget, event): def on_after_nickname_textview_focus_out_event(self, widget, event):
gajim.config.set('after_nickname', widget.get_text().decode('utf-8')) text = self._get_textview_text(widget)
text = helpers.to_one_line(text)
gajim.config.set('after_nickname', text)
gajim.interface.save_config() gajim.interface.save_config()
def update_text_tags(self): def update_text_tags(self):
@ -1064,6 +1089,13 @@ class PreferencesWindow:
gajim.interface.instances['advanced_config'] = \ gajim.interface.instances['advanced_config'] = \
dialogs.AdvancedConfigurationWindow() dialogs.AdvancedConfigurationWindow()
def set_status_msg_from_current_music_track_checkbutton_toggled(self,
widget):
self.on_checkbutton_toggled(widget,
'set_status_msg_from_current_music_track')
gajim.interface.roster.enable_syncing_status_msg_from_current_music_track(
widget.get_active())
#---------- AccountModificationWindow class -------------# #---------- AccountModificationWindow class -------------#
class AccountModificationWindow: class AccountModificationWindow:
'''Class for account informations''' '''Class for account informations'''
@ -1101,7 +1133,8 @@ class AccountModificationWindow:
def init_account_gpg(self): def init_account_gpg(self):
keyid = gajim.config.get_per('accounts', self.account, 'keyid') keyid = gajim.config.get_per('accounts', self.account, 'keyid')
keyname = gajim.config.get_per('accounts', self.account, 'keyname') keyname = gajim.config.get_per('accounts', self.account, 'keyname')
savegpgpass = gajim.config.get_per('accounts', self.account,'savegpgpass') savegpgpass = gajim.config.get_per('accounts', self.account,
'savegpgpass')
if not keyid or not gajim.config.get('usegpg'): if not keyid or not gajim.config.get('usegpg'):
return return
@ -1358,8 +1391,7 @@ class AccountModificationWindow:
gajim.events.change_account_name(self.account, name) gajim.events.change_account_name(self.account, name)
# change account variable for chat / gc controls # change account variable for chat / gc controls
for ctrl in gajim.interface.msg_win_mgr.get_controls(): gajim.interface.msg_win_mgr.change_account_name(self.account, name)
ctrl.account = name
# upgrade account variable in opened windows # upgrade account variable in opened windows
for kind in ('infos', 'disco', 'gc_config'): for kind in ('infos', 'disco', 'gc_config'):
for j in gajim.interface.instances[name][kind]: for j in gajim.interface.instances[name][kind]:
@ -1858,6 +1890,7 @@ class AccountsWindow:
gajim.interface.roster.regroup = False gajim.interface.roster.regroup = False
gajim.interface.roster.draw_roster() gajim.interface.roster.draw_roster()
def on_enable_zeroconf_checkbutton_toggled(self, widget): def on_enable_zeroconf_checkbutton_toggled(self, widget):
if gajim.config.get('enable_zeroconf'): if gajim.config.get('enable_zeroconf'):
#disable #disable
@ -2987,9 +3020,6 @@ _('You can set advanced account options by pressing Advanced button, or later by
con = connection.Connection(self.account) con = connection.Connection(self.account)
con.password = password con.password = password
if not savepass:
password = ""
config = {} config = {}
config['name'] = login config['name'] = login
config['hostname'] = server config['hostname'] = server
@ -3018,6 +3048,10 @@ _('You can set advanced account options by pressing Advanced button, or later by
def create_vars(self, config): def create_vars(self, config):
gajim.config.add_per('accounts', self.account) gajim.config.add_per('accounts', self.account)
if not config['savepass']:
config['password'] = ''
for opt in config: for opt in config:
gajim.config.set_per('accounts', self.account, opt, config[opt]) gajim.config.set_per('accounts', self.account, opt, config[opt])

View file

@ -139,6 +139,9 @@ class ConversationTextview:
self.line_tooltip = tooltips.BaseTooltip() self.line_tooltip = tooltips.BaseTooltip()
path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'muc_separator.png')
self.focus_out_line_pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file)
def del_handlers(self): def del_handlers(self):
for i in self.handlers.keys(): for i in self.handlers.keys():
if self.handlers[i].handler_is_connected(i): if self.handlers[i].handler_is_connected(i):
@ -230,19 +233,14 @@ class ConversationTextview:
end_iter_for_previous_line) end_iter_for_previous_line)
# add the new focus out line # add the new focus out line
# FIXME: Why is this loaded from disk everytime
path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'muc_separator.png')
focus_out_line_pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file)
end_iter = buffer.get_end_iter() end_iter = buffer.get_end_iter()
buffer.insert(end_iter, '\n') buffer.insert(end_iter, '\n')
buffer.insert_pixbuf(end_iter, focus_out_line_pixbuf) buffer.insert_pixbuf(end_iter, self.focus_out_line_pixbuf)
end_iter = buffer.get_end_iter() end_iter = buffer.get_end_iter()
before_img_iter = end_iter.copy() before_img_iter = end_iter.copy()
before_img_iter.backward_char() # one char back (an image also takes one char) before_img_iter.backward_char() # one char back (an image also takes one char)
buffer.apply_tag_by_name('focus-out-line', before_img_iter, end_iter) buffer.apply_tag_by_name('focus-out-line', before_img_iter, end_iter)
#FIXME: remove this workaround when bug is fixed
# c http://bugzilla.gnome.org/show_bug.cgi?id=318569
self.allow_focus_out_line = False self.allow_focus_out_line = False
@ -562,6 +560,7 @@ class ConversationTextview:
img.show() img.show()
#add with possible animation #add with possible animation
self.tv.add_child_at_anchor(img, anchor) self.tv.add_child_at_anchor(img, anchor)
#FIXME: one day, somehow sync with regexp in gajim.py
elif special_text.startswith('http://') or \ elif special_text.startswith('http://') or \
special_text.startswith('www.') or \ special_text.startswith('www.') or \
special_text.startswith('ftp://') or \ special_text.startswith('ftp://') or \
@ -664,7 +663,9 @@ class ConversationTextview:
current_print_time = gajim.config.get('print_time') current_print_time = gajim.config.get('print_time')
if current_print_time == 'always' and kind != 'info': if current_print_time == 'always' and kind != 'info':
before_str = gajim.config.get('before_time') before_str = gajim.config.get('before_time')
before_str = helpers.from_one_line(before_str)
after_str = gajim.config.get('after_time') after_str = gajim.config.get('after_time')
after_str = helpers.from_one_line(after_str)
# get difference in days since epoch (86400 = 24*3600) # get difference in days since epoch (86400 = 24*3600)
# number of days since epoch for current time (in GMT) - # number of days since epoch for current time (in GMT) -
# number of days since epoch for message (in GMT) # number of days since epoch for message (in GMT)
@ -748,7 +749,9 @@ class ConversationTextview:
name_tags = other_tags_for_name[:] # create a new list name_tags = other_tags_for_name[:] # create a new list
name_tags.append(kind) name_tags.append(kind)
before_str = gajim.config.get('before_nickname') before_str = gajim.config.get('before_nickname')
before_str = helpers.from_one_line(before_str)
after_str = gajim.config.get('after_nickname') after_str = gajim.config.get('after_nickname')
after_str = helpers.from_one_line(after_str)
format = before_str + name + after_str + ' ' format = before_str + name + after_str + ' '
buffer.insert_with_tags_by_name(end_iter, format, *name_tags) buffer.insert_with_tags_by_name(end_iter, format, *name_tags)

View file

@ -23,25 +23,17 @@ from common import exceptions
try: try:
import dbus import dbus
version = getattr(dbus, 'version', (0, 20, 0)) import dbus.service
supported = True import dbus.glib
supported = True # does use have D-Bus bindings?
except ImportError: except ImportError:
version = (0, 0, 0)
supported = False supported = False
if not os.name == 'nt': # only say that to non Windows users if not os.name == 'nt': # only say that to non Windows users
print _('D-Bus python bindings are missing in this computer') print _('D-Bus python bindings are missing in this computer')
print _('D-Bus capabilities of Gajim cannot be used') print _('D-Bus capabilities of Gajim cannot be used')
# dbus 0.23 leads to segfault with threads_init()
if sys.version[:4] >= '2.4' and version[1] < 30:
supported = False
if version >= (0, 41, 0):
import dbus.service
import dbus.glib # cause dbus 0.35+ doesn't return signal replies without it
class SessionBus: class SessionBus:
'''A Singleton for the DBus SessionBus''' '''A Singleton for the D-Bus SessionBus'''
def __init__(self): def __init__(self):
self.session_bus = None self.session_bus = None

View file

@ -837,27 +837,31 @@ class FileChooserDialog(gtk.FileChooserDialog):
self.set_current_folder(current_folder) self.set_current_folder(current_folder)
else: else:
self.set_current_folder(helpers.get_documents_path()) self.set_current_folder(helpers.get_documents_path())
self.response_ok, self.response_cancel = \
buttons = self.action_area.get_children() on_response_ok, on_response_cancel
possible_responses = {gtk.STOCK_OPEN: on_response_ok, # in gtk+-2.10 clicked signal on some of the buttons in a dialog
gtk.STOCK_SAVE: on_response_ok, # is emitted twice, so we cannot rely on 'clicked' signal
gtk.STOCK_CANCEL: on_response_cancel} self.connect('response', self.on_dialog_response)
for b in buttons:
for response in possible_responses:
if b.get_label() == response:
if not possible_responses[response]:
b.connect('clicked', self.just_destroy)
elif isinstance(possible_responses[response], tuple):
if len(possible_responses[response]) == 1:
b.connect('clicked', possible_responses[response][0])
else:
b.connect('clicked', *possible_responses[response])
else:
b.connect('clicked', possible_responses[response])
break
self.show_all() self.show_all()
def on_dialog_response(self, dialog, response):
if response in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_CLOSE):
if self.response_cancel:
if isinstance(self.response_cancel, tuple):
self.response_cancel[0](dialog, *self.response_cancel[1:])
else:
self.response_cancel(dialog)
else:
self.just_destroy(dialog)
elif response == gtk.RESPONSE_OK:
if self.response_ok:
if isinstance(self.response_ok, tuple):
self.response_ok[0](dialog, *self.response_ok[1:])
else:
self.response_ok(dialog)
else:
self.just_destroy(dialog)
def just_destroy(self, widget): def just_destroy(self, widget):
self.destroy() self.destroy()
@ -1192,7 +1196,7 @@ class NewChatDialog(InputDialog):
title = _('Start Chat with account %s') % account title = _('Start Chat with account %s') % account
else: else:
title = _('Start Chat') title = _('Start Chat')
prompt_text = _('Fill in the jid, or nick of the contact you would like\nto send a chat message to:') prompt_text = _('Fill in the nickname or the Jabber ID of the contact you would like\nto send a chat message to:')
InputDialog.__init__(self, title, prompt_text, is_modal = False) InputDialog.__init__(self, title, prompt_text, is_modal = False)
self.completion_dict = {} self.completion_dict = {}
@ -1725,10 +1729,13 @@ class XMLConsoleWindow:
self.input_textview.grab_focus() self.input_textview.grab_focus()
class PrivacyListWindow: class PrivacyListWindow:
def __init__(self, account, privacy_list, list_type): '''Window that is used for creating NEW or EDITING already there privacy
'''list_type can be 0 if list is created or 1 if it id edited''' lists'''
def __init__(self, account, privacy_list_name, action):
'''action is 'edit' or 'new' depending on if we create a new priv list
or edit an already existing one'''
self.account = account self.account = account
self.privacy_list = privacy_list self.privacy_list_name = privacy_list_name
# Dicts and Default Values # Dicts and Default Values
self.active_rule = '' self.active_rule = ''
@ -1740,7 +1747,7 @@ class PrivacyListWindow:
self.allow_deny = 'allow' self.allow_deny = 'allow'
# Connect to glade # Connect to glade
self.xml = gtkgui_helpers.get_glade('privacy_list_edit_window.glade') self.xml = gtkgui_helpers.get_glade('privacy_list_window.glade')
self.window = self.xml.get_widget('privacy_list_edit_window') self.window = self.xml.get_widget('privacy_list_edit_window')
# Add Widgets # Add Widgets
@ -1762,10 +1769,10 @@ class PrivacyListWindow:
'privacy_list_default_checkbutton']: 'privacy_list_default_checkbutton']:
self.__dict__[widget_to_add] = self.xml.get_widget(widget_to_add) self.__dict__[widget_to_add] = self.xml.get_widget(widget_to_add)
# Send translations
self.privacy_lists_title_label.set_label( self.privacy_lists_title_label.set_label(
_('Privacy List <b><i>%s</i></b>') % \ _('Privacy List <b><i>%s</i></b>') % \
gtkgui_helpers.escape_for_pango_markup(self.privacy_list)) gtkgui_helpers.escape_for_pango_markup(self.privacy_list_name))
if len(gajim.connections) > 1: if len(gajim.connections) > 1:
title = _('Privacy List for %s') % self.account title = _('Privacy List for %s') % self.account
@ -1777,8 +1784,7 @@ class PrivacyListWindow:
self.privacy_list_active_checkbutton.set_sensitive(False) self.privacy_list_active_checkbutton.set_sensitive(False)
self.privacy_list_default_checkbutton.set_sensitive(False) self.privacy_list_default_checkbutton.set_sensitive(False)
# Check if list is created (0) or edited (1) if action == 'edit':
if list_type == 1:
self.refresh_rules() self.refresh_rules()
count = 0 count = 0
@ -1799,16 +1805,16 @@ class PrivacyListWindow:
def on_privacy_list_edit_window_destroy(self, widget): def on_privacy_list_edit_window_destroy(self, widget):
'''close window''' '''close window'''
if gajim.interface.instances[self.account].has_key('privacy_list_%s' % \ if gajim.interface.instances[self.account].has_key('privacy_list_%s' % \
self.privacy_list): self.privacy_list_name):
del gajim.interface.instances[self.account]['privacy_list_%s' % \ del gajim.interface.instances[self.account]['privacy_list_%s' % \
self.privacy_list] self.privacy_list_name]
def check_active_default(self, a_d_dict): def check_active_default(self, a_d_dict):
if a_d_dict['active'] == self.privacy_list: if a_d_dict['active'] == self.privacy_list_name:
self.privacy_list_active_checkbutton.set_active(True) self.privacy_list_active_checkbutton.set_active(True)
else: else:
self.privacy_list_active_checkbutton.set_active(False) self.privacy_list_active_checkbutton.set_active(False)
if a_d_dict['default'] == self.privacy_list: if a_d_dict['default'] == self.privacy_list_name:
self.privacy_list_default_checkbutton.set_active(True) self.privacy_list_default_checkbutton.set_active(True)
else: else:
self.privacy_list_default_checkbutton.set_active(False) self.privacy_list_default_checkbutton.set_active(False)
@ -1845,7 +1851,7 @@ class PrivacyListWindow:
gajim.connections[self.account].get_active_default_lists() gajim.connections[self.account].get_active_default_lists()
def refresh_rules(self): def refresh_rules(self):
gajim.connections[self.account].get_privacy_list(self.privacy_list) gajim.connections[self.account].get_privacy_list(self.privacy_list_name)
def on_delete_rule_button_clicked(self, widget): def on_delete_rule_button_clicked(self, widget):
tags = [] tags = []
@ -1854,7 +1860,7 @@ class PrivacyListWindow:
self.list_of_rules_combobox.get_active_text().decode('utf-8'): self.list_of_rules_combobox.get_active_text().decode('utf-8'):
tags.append(self.global_rules[rule]) tags.append(self.global_rules[rule])
gajim.connections[self.account].set_privacy_list( gajim.connections[self.account].set_privacy_list(
self.privacy_list, tags) self.privacy_list_name, tags)
self.privacy_list_received(tags) self.privacy_list_received(tags)
self.add_edit_vbox.hide() self.add_edit_vbox.hide()
@ -1918,13 +1924,13 @@ class PrivacyListWindow:
def on_privacy_list_active_checkbutton_toggled(self, widget): def on_privacy_list_active_checkbutton_toggled(self, widget):
if widget.get_active(): if widget.get_active():
gajim.connections[self.account].set_active_list(self.privacy_list) gajim.connections[self.account].set_active_list(self.privacy_list_name)
else: else:
gajim.connections[self.account].set_active_list(None) gajim.connections[self.account].set_active_list(None)
def on_privacy_list_default_checkbutton_toggled(self, widget): def on_privacy_list_default_checkbutton_toggled(self, widget):
if widget.get_active(): if widget.get_active():
gajim.connections[self.account].set_default_list(self.privacy_list) gajim.connections[self.account].set_default_list(self.privacy_list_name)
else: else:
gajim.connections[self.account].set_default_list(None) gajim.connections[self.account].set_default_list(None)
@ -1994,7 +2000,7 @@ class PrivacyListWindow:
else: else:
tags.append(current_tags) tags.append(current_tags)
gajim.connections[self.account].set_privacy_list(self.privacy_list, tags) gajim.connections[self.account].set_privacy_list(self.privacy_list_name, tags)
self.privacy_list_received(tags) self.privacy_list_received(tags)
self.add_edit_vbox.hide() self.add_edit_vbox.hide()
@ -2019,7 +2025,9 @@ class PrivacyListWindow:
self.add_edit_vbox.hide() self.add_edit_vbox.hide()
class PrivacyListsWindow: class PrivacyListsWindow:
# To do: UTF-8 ??????? '''Window that is the main window for Privacy Lists;
we can list there the privacy lists and ask to create a new one
or edit an already there one'''
def __init__(self, account): def __init__(self, account):
self.account = account self.account = account
@ -2027,7 +2035,7 @@ class PrivacyListsWindow:
self.privacy_lists_save = [] self.privacy_lists_save = []
self.xml = gtkgui_helpers.get_glade('privacy_lists_first_window.glade') self.xml = gtkgui_helpers.get_glade('privacy_lists_window.glade')
self.window = self.xml.get_widget('privacy_lists_first_window') self.window = self.xml.get_widget('privacy_lists_first_window')
for widget_to_add in ['list_of_privacy_lists_combobox', for widget_to_add in ['list_of_privacy_lists_combobox',
@ -2107,7 +2115,7 @@ class PrivacyListsWindow:
window.present() window.present()
else: else:
gajim.interface.instances[self.account]['privacy_list_%s' % name] = \ gajim.interface.instances[self.account]['privacy_list_%s' % name] = \
PrivacyListWindow(self.account, name, 0) PrivacyListWindow(self.account, name, 'new')
self.new_privacy_list_entry.set_text('') self.new_privacy_list_entry.set_text('')
def on_privacy_lists_refresh_button_clicked(self, widget): def on_privacy_lists_refresh_button_clicked(self, widget):
@ -2122,7 +2130,7 @@ class PrivacyListsWindow:
window.present() window.present()
else: else:
gajim.interface.instances[self.account]['privacy_list_%s' % name] = \ gajim.interface.instances[self.account]['privacy_list_%s' % name] = \
PrivacyListWindow(self.account, name, 1) PrivacyListWindow(self.account, name, 'edit')
class InvitationReceivedDialog: class InvitationReceivedDialog:
def __init__(self, account, room_jid, contact_jid, password = None, comment = None): def __init__(self, account, room_jid, contact_jid, password = None, comment = None):
@ -2291,6 +2299,18 @@ class ImageChooserDialog(FileChooserDialog):
return return
widget.get_preview_widget().set_from_pixbuf(pixbuf) widget.get_preview_widget().set_from_pixbuf(pixbuf)
class AvatarChooserDialog(ImageChooserDialog):
def __init__(self, path_to_file = '', on_response_ok = None,
on_response_cancel = None, on_response_clear = None):
ImageChooserDialog.__init__(self, path_to_file, on_response_ok,
on_response_cancel)
button = gtk.Button(None, gtk.STOCK_CLEAR)
if on_response_clear:
button.connect('clicked', on_response_clear)
button.show_all()
self.action_area.pack_start(button)
self.action_area.reorder_child(button, 0)
class AddSpecialNotificationDialog: class AddSpecialNotificationDialog:
def __init__(self, jid): def __init__(self, jid):
'''jid is the jid for which we want to add special notification '''jid is the jid for which we want to add special notification

View file

@ -36,10 +36,10 @@
# - def update_actions(self) # - def update_actions(self)
# - def default_action(self) # - def default_action(self)
# - def _find_item(self, jid, node) # - def _find_item(self, jid, node)
# - def _add_item(self, model, jid, node, item, force) # - def _add_item(self, jid, node, item, force)
# - def _update_item(self, model, iter, jid, node, item) # - def _update_item(self, iter, jid, node, item)
# - def _update_info(self, model, iter, jid, node, identities, features, data) # - def _update_info(self, iter, jid, node, identities, features, data)
# - def _update_error(self, model, iter, jid, node) # - def _update_error(self, iter, jid, node)
# #
# * Should call the super class for this method. # * Should call the super class for this method.
# All others do not have to call back to the super class. (but can if they want # All others do not have to call back to the super class. (but can if they want
@ -215,8 +215,8 @@ class ServicesCache:
ServiceCache instance.''' ServiceCache instance.'''
def __init__(self, account): def __init__(self, account):
self.account = account self.account = account
self._items = CacheDictionary(15, getrefresh = False) self._items = CacheDictionary(1, getrefresh = True)
self._info = CacheDictionary(15, getrefresh = False) self._info = CacheDictionary(1, getrefresh = True)
self._cbs = {} self._cbs = {}
def _clean_closure(self, cb, type, addr): def _clean_closure(self, cb, type, addr):
@ -422,6 +422,7 @@ _('Without a connection, you can not browse available services'))
self.xml = gtkgui_helpers.get_glade('service_discovery_window.glade') self.xml = gtkgui_helpers.get_glade('service_discovery_window.glade')
self.window = self.xml.get_widget('service_discovery_window') self.window = self.xml.get_widget('service_discovery_window')
self.services_treeview = self.xml.get_widget('services_treeview') self.services_treeview = self.xml.get_widget('services_treeview')
self.model = None
# This is more reliable than the cursor-changed signal. # This is more reliable than the cursor-changed signal.
selection = self.services_treeview.get_selection() selection = self.services_treeview.get_selection()
selection.connect_after('changed', selection.connect_after('changed',
@ -452,7 +453,6 @@ _('Without a connection, you can not browse available services'))
liststore = gtk.ListStore(str) liststore = gtk.ListStore(str)
self.address_comboboxentry.set_model(liststore) self.address_comboboxentry.set_model(liststore)
self.address_comboboxentry.set_text_column(0)
self.latest_addresses = gajim.config.get( self.latest_addresses = gajim.config.get(
'latest_disco_addresses').split() 'latest_disco_addresses').split()
if jid in self.latest_addresses: if jid in self.latest_addresses:
@ -720,9 +720,9 @@ class AgentBrowser:
note that the first two columns should ALWAYS be of type string and note that the first two columns should ALWAYS be of type string and
contain the JID and node of the item respectively.''' contain the JID and node of the item respectively.'''
# JID, node, name, address # JID, node, name, address
model = gtk.ListStore(str, str, str, str) self.model = gtk.ListStore(str, str, str, str)
model.set_sort_column_id(3, gtk.SORT_ASCENDING) self.model.set_sort_column_id(3, gtk.SORT_ASCENDING)
self.window.services_treeview.set_model(model) self.window.services_treeview.set_model(self.model)
# Name column # Name column
col = gtk.TreeViewColumn(_('Name')) col = gtk.TreeViewColumn(_('Name'))
renderer = gtk.CellRendererText() renderer = gtk.CellRendererText()
@ -740,7 +740,7 @@ class AgentBrowser:
self.window.services_treeview.set_headers_visible(True) self.window.services_treeview.set_headers_visible(True)
def _clean_treemodel(self): def _clean_treemodel(self):
self.window.services_treeview.get_model().clear() self.model.clear()
for col in self.window.services_treeview.get_columns(): for col in self.window.services_treeview.get_columns():
self.window.services_treeview.remove_column(col) self.window.services_treeview.remove_column(col)
self.window.services_treeview.set_headers_visible(False) self.window.services_treeview.set_headers_visible(False)
@ -872,8 +872,7 @@ class AgentBrowser:
def browse(self, force = False): def browse(self, force = False):
'''Fill the treeview with agents, fetching the info if necessary.''' '''Fill the treeview with agents, fetching the info if necessary.'''
model = self.window.services_treeview.get_model() self.model.clear()
model.clear()
self._total_items = self._progress = 0 self._total_items = self._progress = 0
self.window.progressbar.show() self.window.progressbar.show()
self._pulse_timeout = gobject.timeout_add(250, self._pulse_timeout_cb) self._pulse_timeout = gobject.timeout_add(250, self._pulse_timeout_cb)
@ -890,21 +889,21 @@ class AgentBrowser:
def _find_item(self, jid, node): def _find_item(self, jid, node):
'''Check if an item is already in the treeview. Return an iter to it '''Check if an item is already in the treeview. Return an iter to it
if so, None otherwise.''' if so, None otherwise.'''
model = self.window.services_treeview.get_model() iter = self.model.get_iter_root()
iter = model.get_iter_root()
while iter: while iter:
cjid = model.get_value(iter, 0).decode('utf-8') cjid = self.model.get_value(iter, 0).decode('utf-8')
cnode = model.get_value(iter, 1).decode('utf-8') cnode = self.model.get_value(iter, 1).decode('utf-8')
if jid == cjid and node == cnode: if jid == cjid and node == cnode:
break break
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
if iter: if iter:
return iter return iter
return None return None
def _agent_items(self, jid, node, items, force): def _agent_items(self, jid, node, items, force):
'''Callback for when we receive a list of agent items.''' '''Callback for when we receive a list of agent items.'''
model = self.window.services_treeview.get_model() self.model.clear()
self._total_items = 0
gobject.source_remove(self._pulse_timeout) gobject.source_remove(self._pulse_timeout)
self.window.progressbar.hide() self.window.progressbar.hide()
# The server returned an error # The server returned an error
@ -916,53 +915,48 @@ class AgentBrowser:
_('This service does not contain any items to browse.')) _('This service does not contain any items to browse.'))
return return
# We got a list of items # We got a list of items
self.window.services_treeview.set_model(None)
for item in items: for item in items:
jid = item['jid'] jid = item['jid']
node = item.get('node', '') node = item.get('node', '')
iter = self._find_item(jid, node)
if iter:
# Already in the treeview
self._update_item(model, iter, jid, node, item)
else:
# Not in the treeview
self._total_items += 1 self._total_items += 1
self._add_item(model, jid, node, item, force) self._add_item(jid, node, item, force)
self.window.services_treeview.set_model(self.model)
def _agent_info(self, jid, node, identities, features, data): def _agent_info(self, jid, node, identities, features, data):
'''Callback for when we receive info about an agent's item.''' '''Callback for when we receive info about an agent's item.'''
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
model = self.window.services_treeview.get_model()
iter = self._find_item(jid, node) iter = self._find_item(jid, node)
if not iter: if not iter:
# Not in the treeview, stop # Not in the treeview, stop
return return
if identities == 0: if identities == 0:
# The server returned an error # The server returned an error
self._update_error(model, iter, jid, node) self._update_error(iter, jid, node)
else: else:
# We got our info # We got our info
self._update_info(model, iter, jid, node, self._update_info(iter, jid, node,
identities, features, data) identities, features, data)
self.update_actions() self.update_actions()
def _add_item(self, model, jid, node, item, force): def _add_item(self, jid, node, item, force):
'''Called when an item should be added to the model. The result of a '''Called when an item should be added to the model. The result of a
disco#items query.''' disco#items query.'''
model.append((jid, node, item.get('name', ''), self.model.append((jid, node, item.get('name', ''),
get_agent_address(jid, node))) get_agent_address(jid, node)))
def _update_item(self, model, iter, jid, node, item): def _update_item(self, iter, jid, node, item):
'''Called when an item should be updated in the model. The result of a '''Called when an item should be updated in the model. The result of a
disco#items query. (seldom)''' disco#items query. (seldom)'''
if item.has_key('name'): if item.has_key('name'):
model[iter][2] = item['name'] self.model[iter][2] = item['name']
def _update_info(self, model, iter, jid, node, identities, features, data): def _update_info(self, iter, jid, node, identities, features, data):
'''Called when an item should be updated in the model with further info. '''Called when an item should be updated in the model with further info.
The result of a disco#info query.''' The result of a disco#info query.'''
model[iter][2] = identities[0].get('name', '') self.model[iter][2] = identities[0].get('name', '')
def _update_error(self, model, iter, jid, node): def _update_error(self, iter, jid, node):
'''Called when a disco#info query failed for an item.''' '''Called when a disco#info query failed for an item.'''
pass pass
@ -1046,14 +1040,12 @@ class ToplevelAgentBrowser(AgentBrowser):
# These are all callbacks to make tooltips work # These are all callbacks to make tooltips work
def on_treeview_leave_notify_event(self, widget, event): def on_treeview_leave_notify_event(self, widget, event):
model = widget.get_model()
props = widget.get_path_at_pos(int(event.x), int(event.y)) props = widget.get_path_at_pos(int(event.x), int(event.y))
if self.tooltip.timeout > 0: if self.tooltip.timeout > 0:
if not props or self.tooltip.id == props[0]: if not props or self.tooltip.id == props[0]:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
def on_treeview_motion_notify_event(self, widget, event): def on_treeview_motion_notify_event(self, widget, event):
model = widget.get_model()
props = widget.get_path_at_pos(int(event.x), int(event.y)) props = widget.get_path_at_pos(int(event.x), int(event.y))
if self.tooltip.timeout > 0: if self.tooltip.timeout > 0:
if not props or self.tooltip.id != props[0]: if not props or self.tooltip.id != props[0]:
@ -1062,12 +1054,12 @@ class ToplevelAgentBrowser(AgentBrowser):
[row, col, x, y] = props [row, col, x, y] = props
iter = None iter = None
try: try:
iter = model.get_iter(row) iter = self.model.get_iter(row)
except: except:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
return return
jid = model[iter][0] jid = self.model[iter][0]
state = model[iter][4] state = self.model[iter][4]
# Not a category, and we have something to say about state # Not a category, and we have something to say about state
if jid and state > 0 and \ if jid and state > 0 and \
(self.tooltip.timeout == 0 or self.tooltip.id != props[0]): (self.tooltip.timeout == 0 or self.tooltip.id != props[0]):
@ -1084,10 +1076,10 @@ class ToplevelAgentBrowser(AgentBrowser):
# JID, node, icon, description, state # JID, node, icon, description, state
# State means 2 when error, 1 when fetching, 0 when succes. # State means 2 when error, 1 when fetching, 0 when succes.
view = self.window.services_treeview view = self.window.services_treeview
model = gtk.TreeStore(str, str, gtk.gdk.Pixbuf, str, int) self.model = gtk.TreeStore(str, str, gtk.gdk.Pixbuf, str, int)
model.set_sort_func(4, self._treemodel_sort_func) self.model.set_sort_func(4, self._treemodel_sort_func)
model.set_sort_column_id(4, gtk.SORT_ASCENDING) self.model.set_sort_column_id(4, gtk.SORT_ASCENDING)
view.set_model(model) view.set_model(self.model)
col = gtk.TreeViewColumn() col = gtk.TreeViewColumn()
# Icon Renderer # Icon Renderer
@ -1329,41 +1321,38 @@ class ToplevelAgentBrowser(AgentBrowser):
def _create_category(self, cat, type=None): def _create_category(self, cat, type=None):
'''Creates a category row.''' '''Creates a category row.'''
model = self.window.services_treeview.get_model()
cat, prio = self._friendly_category(cat, type) cat, prio = self._friendly_category(cat, type)
return model.append(None, ('', '', None, cat, prio)) return self.model.append(None, ('', '', None, cat, prio))
def _find_category(self, cat, type=None): def _find_category(self, cat, type=None):
'''Looks up a category row and returns the iterator to it, or None.''' '''Looks up a category row and returns the iterator to it, or None.'''
model = self.window.services_treeview.get_model()
cat, prio = self._friendly_category(cat, type) cat, prio = self._friendly_category(cat, type)
iter = model.get_iter_root() iter = self.model.get_iter_root()
while iter: while iter:
if model.get_value(iter, 3).decode('utf-8') == cat: if self.model.get_value(iter, 3).decode('utf-8') == cat:
break break
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
if iter: if iter:
return iter return iter
return None return None
def _find_item(self, jid, node): def _find_item(self, jid, node):
model = self.window.services_treeview.get_model()
iter = None iter = None
cat_iter = model.get_iter_root() cat_iter = self.model.get_iter_root()
while cat_iter and not iter: while cat_iter and not iter:
iter = model.iter_children(cat_iter) iter = self.model.iter_children(cat_iter)
while iter: while iter:
cjid = model.get_value(iter, 0).decode('utf-8') cjid = self.model.get_value(iter, 0).decode('utf-8')
cnode = model.get_value(iter, 1).decode('utf-8') cnode = self.model.get_value(iter, 1).decode('utf-8')
if jid == cjid and node == cnode: if jid == cjid and node == cnode:
break break
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
cat_iter = model.iter_next(cat_iter) cat_iter = self.model.iter_next(cat_iter)
if iter: if iter:
return iter return iter
return None return None
def _add_item(self, model, jid, node, item, force): def _add_item(self, jid, node, item, force):
# Row text # Row text
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
if item.has_key('name'): if item.has_key('name'):
@ -1387,21 +1376,21 @@ class ToplevelAgentBrowser(AgentBrowser):
cat = self._find_category(*cat_args) cat = self._find_category(*cat_args)
if not cat: if not cat:
cat = self._create_category(*cat_args) cat = self._create_category(*cat_args)
model.append(cat, (item['jid'], item.get('node', ''), pix, descr, 1)) self.model.append(cat, (item['jid'], item.get('node', ''), pix, descr, 1))
self._expand_all() self._expand_all()
# Grab info on the service # Grab info on the service
self.cache.get_info(jid, node, self._agent_info, force = force) self.cache.get_info(jid, node, self._agent_info, force = force)
self._update_progressbar() self._update_progressbar()
def _update_item(self, model, iter, jid, node, item): def _update_item(self, iter, jid, node, item):
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
if item.has_key('name'): if item.has_key('name'):
descr = "<b>%s</b>\n%s" % (item['name'], addr) descr = "<b>%s</b>\n%s" % (item['name'], addr)
else: else:
descr = "<b>%s</b>" % addr descr = "<b>%s</b>" % addr
model[iter][3] = descr self.model[iter][3] = descr
def _update_info(self, model, iter, jid, node, identities, features, data): def _update_info(self, iter, jid, node, identities, features, data):
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
name = identities[0].get('name', '') name = identities[0].get('name', '')
if name: if name:
@ -1423,32 +1412,32 @@ class ToplevelAgentBrowser(AgentBrowser):
break break
# Check if we have to move categories # Check if we have to move categories
old_cat_iter = model.iter_parent(iter) old_cat_iter = self.model.iter_parent(iter)
old_cat = model.get_value(old_cat_iter, 3).decode('utf-8') old_cat = self.model.get_value(old_cat_iter, 3).decode('utf-8')
if model.get_value(old_cat_iter, 3) == cat: if self.model.get_value(old_cat_iter, 3) == cat:
# Already in the right category, just update # Already in the right category, just update
model[iter][2] = pix self.model[iter][2] = pix
model[iter][3] = descr self.model[iter][3] = descr
model[iter][4] = 0 self.model[iter][4] = 0
return return
# Not in the right category, move it. # Not in the right category, move it.
model.remove(iter) self.model.remove(iter)
# Check if the old category is empty # Check if the old category is empty
if not model.iter_is_valid(old_cat_iter): if not self.model.iter_is_valid(old_cat_iter):
old_cat_iter = self._find_category(old_cat) old_cat_iter = self._find_category(old_cat)
if not model.iter_children(old_cat_iter): if not self.model.iter_children(old_cat_iter):
model.remove(old_cat_iter) self.model.remove(old_cat_iter)
cat_iter = self._find_category(cat, type) cat_iter = self._find_category(cat, type)
if not cat_iter: if not cat_iter:
cat_iter = self._create_category(cat, type) cat_iter = self._create_category(cat, type)
model.append(cat_iter, (jid, node, pix, descr, 0)) self.model.append(cat_iter, (jid, node, pix, descr, 0))
self._expand_all() self._expand_all()
def _update_error(self, model, iter, jid, node): def _update_error(self, iter, jid, node):
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
model[iter][4] = 2 self.model[iter][4] = 2
self._progress += 1 self._progress += 1
self._update_progressbar() self._update_progressbar()
@ -1462,11 +1451,13 @@ class MucBrowser(AgentBrowser):
# JID, node, name, users, description, fetched # JID, node, name, users, description, fetched
# This is rather long, I'd rather not use a data_func here though. # This is rather long, I'd rather not use a data_func here though.
# Users is a string, because want to be able to leave it empty. # Users is a string, because want to be able to leave it empty.
model = gtk.ListStore(str, str, str, str, str, bool) self.model = gtk.ListStore(str, str, str, str, str, bool)
model.set_sort_column_id(2, gtk.SORT_ASCENDING) self.model.set_sort_column_id(2, gtk.SORT_ASCENDING)
self.window.services_treeview.set_model(model) self.window.services_treeview.set_model(self.model)
# Name column # Name column
col = gtk.TreeViewColumn(_('Name')) col = gtk.TreeViewColumn(_('Name'))
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_fixed_width(100)
renderer = gtk.CellRendererText() renderer = gtk.CellRendererText()
col.pack_start(renderer) col.pack_start(renderer)
col.set_attributes(renderer, text = 2) col.set_attributes(renderer, text = 2)
@ -1486,6 +1477,13 @@ class MucBrowser(AgentBrowser):
col.set_attributes(renderer, text = 4) col.set_attributes(renderer, text = 4)
self.window.services_treeview.insert_column(col, -1) self.window.services_treeview.insert_column(col, -1)
col.set_resizable(True) col.set_resizable(True)
# Id column
col = gtk.TreeViewColumn(_('Id'))
renderer = gtk.CellRendererText()
col.pack_start(renderer)
col.set_attributes(renderer, text = 0)
self.window.services_treeview.insert_column(col, -1)
col.set_resizable(True)
self.window.services_treeview.set_headers_visible(True) self.window.services_treeview.set_headers_visible(True)
# Source id for idle callback used to start disco#info queries. # Source id for idle callback used to start disco#info queries.
self._fetch_source = None self._fetch_source = None
@ -1568,7 +1566,6 @@ class MucBrowser(AgentBrowser):
# Prevent a silly warning, try again in a bit. # Prevent a silly warning, try again in a bit.
self._fetch_source = gobject.timeout_add(100, self._start_info_query) self._fetch_source = gobject.timeout_add(100, self._start_info_query)
return return
model = view.get_model()
# We have to do this in a pygtk <2.8 compatible way :/ # We have to do this in a pygtk <2.8 compatible way :/
#start, end = self.window.services_treeview.get_visible_range() #start, end = self.window.services_treeview.get_visible_range()
rect = view.get_visible_rect() rect = view.get_visible_rect()
@ -1577,7 +1574,7 @@ class MucBrowser(AgentBrowser):
try: try:
sx, sy = view.tree_to_widget_coords(rect.x, rect.y) sx, sy = view.tree_to_widget_coords(rect.x, rect.y)
spath = view.get_path_at_pos(sx, sy)[0] spath = view.get_path_at_pos(sx, sy)[0]
iter = model.get_iter(spath) iter = self.model.get_iter(spath)
except TypeError: except TypeError:
self._fetch_source = None self._fetch_source = None
return return
@ -1591,14 +1588,14 @@ class MucBrowser(AgentBrowser):
except TypeError: except TypeError:
# We're at the end of the model, we can leave end=None though. # We're at the end of the model, we can leave end=None though.
pass pass
while iter and model.get_path(iter) != end: while iter and self.model.get_path(iter) != end:
if not model.get_value(iter, 5): if not self.model.get_value(iter, 5):
jid = model.get_value(iter, 0).decode('utf-8') jid = self.model.get_value(iter, 0).decode('utf-8')
node = model.get_value(iter, 1).decode('utf-8') node = self.model.get_value(iter, 1).decode('utf-8')
self.cache.get_info(jid, node, self._agent_info) self.cache.get_info(jid, node, self._agent_info)
self._fetch_source = True self._fetch_source = True
return return
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
self._fetch_source = None self._fetch_source = None
def _channel_altinfo(self, jid, node, items, name = None): def _channel_altinfo(self, jid, node, items, name = None):
@ -1619,22 +1616,21 @@ class MucBrowser(AgentBrowser):
self._fetch_source = None self._fetch_source = None
return return
else: else:
model = self.window.services_treeview.get_model()
iter = self._find_item(jid, node) iter = self._find_item(jid, node)
if iter: if iter:
if name: if name:
model[iter][2] = name self.model[iter][2] = name
model[iter][3] = len(items) # The number of users self.model[iter][3] = len(items) # The number of users
model[iter][5] = True self.model[iter][5] = True
self._fetch_source = None self._fetch_source = None
self._query_visible() self._query_visible()
def _add_item(self, model, jid, node, item, force): def _add_item(self, jid, node, item, force):
model.append((jid, node, item.get('name', ''), '', '', False)) self.model.append((jid, node, item.get('name', ''), '', '', False))
if not self._fetch_source: if not self._fetch_source:
self._fetch_source = gobject.idle_add(self._start_info_query) self._fetch_source = gobject.idle_add(self._start_info_query)
def _update_info(self, model, iter, jid, node, identities, features, data): def _update_info(self, iter, jid, node, identities, features, data):
name = identities[0].get('name', '') name = identities[0].get('name', '')
for form in data: for form in data:
typefield = form.getField('FORM_TYPE') typefield = form.getField('FORM_TYPE')
@ -1644,14 +1640,14 @@ class MucBrowser(AgentBrowser):
users = form.getField('muc#roominfo_occupants') users = form.getField('muc#roominfo_occupants')
descr = form.getField('muc#roominfo_description') descr = form.getField('muc#roominfo_description')
if users: if users:
model[iter][3] = users.getValue() self.model[iter][3] = users.getValue()
if descr: if descr:
model[iter][4] = descr.getValue() self.model[iter][4] = descr.getValue()
# Only set these when we find a form with additional info # Only set these when we find a form with additional info
# Some servers don't support forms and put extra info in # Some servers don't support forms and put extra info in
# the name attribute, so we preserve it in that case. # the name attribute, so we preserve it in that case.
model[iter][2] = name self.model[iter][2] = name
model[iter][5] = True self.model[iter][5] = True
break break
else: else:
# We didn't find a form, switch to alternate query mode # We didn't find a form, switch to alternate query mode
@ -1661,7 +1657,7 @@ class MucBrowser(AgentBrowser):
self._fetch_source = None self._fetch_source = None
self._query_visible() self._query_visible()
def _update_error(self, model, iter, jid, node): def _update_error(self, iter, jid, node):
# switch to alternate query mode # switch to alternate query mode
self.cache.get_items(jid, node, self._channel_altinfo) self.cache.get_items(jid, node, self._channel_altinfo)

View file

@ -246,11 +246,16 @@ _('Connection with peer cannot be established.'))
gtk.RESPONSE_OK, gtk.RESPONSE_OK,
True, # select multiple true as we can select many files to send True, # select multiple true as we can select many files to send
gajim.config.get('last_send_dir'), gajim.config.get('last_send_dir'),
on_response_ok = on_ok,
on_response_cancel = lambda e:dialog.destroy()
) )
btn = dialog.add_button(_('_Send'), gtk.RESPONSE_OK) btn = gtk.Button(_('_Send'))
btn.set_use_stock(True) # FIXME: add send icon to this button (JUMP_TO) btn.set_property('can-default', True)
btn.connect('clicked', on_ok) # FIXME: add send icon to this button (JUMP_TO)
dialog.add_action_widget(btn, gtk.RESPONSE_OK)
dialog.set_default_response(gtk.RESPONSE_OK)
btn.show()
def send_file(self, account, contact, file_path): def send_file(self, account, contact, file_path):
''' start the real transfer(upload) of the file ''' ''' start the real transfer(upload) of the file '''
@ -450,8 +455,10 @@ _('Connection with peer cannot be established.'))
for ev_type in ('file-error', 'file-completed', 'file-request-error', for ev_type in ('file-error', 'file-completed', 'file-request-error',
'file-send-error', 'file-stopped'): 'file-send-error', 'file-stopped'):
for event in gajim.events.get_events(account, jid, [ev_type]): for event in gajim.events.get_events(account, jid, [ev_type]):
if event.parameters[1]['sid'] == file_props['sid']: if event.parameters['sid'] == file_props['sid']:
gajim.events.remove_events(account, jid, event) gajim.events.remove_events(account, jid, event)
gajim.interface.roster.draw_contact(jid, account)
gajim.interface.roster.show_title()
del(self.files_props[sid[0]][sid[1:]]) del(self.files_props[sid[0]][sid[1:]])
del(file_props) del(file_props)

View file

@ -51,13 +51,10 @@ def send_error(error_message):
try: try:
import dbus import dbus
except:
raise exceptions.DbusNotSupported
_version = getattr(dbus, 'version', (0, 20, 0))
if _version[1] >= 41:
import dbus.service import dbus.service
import dbus.glib import dbus.glib
except:
raise exceptions.DbusNotSupported
OBJ_PATH = '/org/gajim/dbus/RemoteObject' OBJ_PATH = '/org/gajim/dbus/RemoteObject'
INTERFACE = 'org.gajim.dbus.RemoteInterface' INTERFACE = 'org.gajim.dbus.RemoteInterface'
@ -320,14 +317,8 @@ class GajimRemote:
except: except:
raise exceptions.SessionBusNotPresent raise exceptions.SessionBusNotPresent
if _version[1] >= 30:
obj = self.sbus.get_object(SERVICE, OBJ_PATH) obj = self.sbus.get_object(SERVICE, OBJ_PATH)
interface = dbus.Interface(obj, INTERFACE) interface = dbus.Interface(obj, INTERFACE)
elif _version[1] < 30:
self.service = self.sbus.get_service(SERVICE)
interface = self.service.get_object(OBJ_PATH, INTERFACE)
else:
send_error(_('Unknown D-Bus version: %s') % _version[1])
# get the function asked # get the function asked
self.method = interface.__getattr__(self.command) self.method = interface.__getattr__(self.command)
@ -447,10 +438,7 @@ class GajimRemote:
''' calls self.method with arguments from sys.argv[2:] ''' ''' calls self.method with arguments from sys.argv[2:] '''
args = sys.argv[2:] args = sys.argv[2:]
args = [i.decode(PREFERRED_ENCODING) for i in sys.argv[2:]] args = [i.decode(PREFERRED_ENCODING) for i in sys.argv[2:]]
if _version[1] >= 41:
args = [dbus.String(i) for i in args] args = [dbus.String(i) for i in args]
else:
args = [i.encode('UTF-8') for i in sys.argv[2:]]
try: try:
res = self.method(*args) res = self.method(*args)
return res return res

View file

@ -552,7 +552,7 @@ class Interface:
chat_control = self.msg_win_mgr.get_control(jid, account) chat_control = self.msg_win_mgr.get_control(jid, account)
# Handle chat states # Handle chat states
contact = gajim.contacts.get_contact(account, jid, resource) contact = gajim.contacts.get_contact(account, jid)
if contact and isinstance(contact, list): if contact and isinstance(contact, list):
contact = contact[0] contact = contact[0]
if contact: if contact:
@ -582,7 +582,10 @@ class Interface:
if gajim.config.get('ignore_unknown_contacts') and \ if gajim.config.get('ignore_unknown_contacts') and \
not gajim.contacts.get_contact(account, jid) and not pm: not gajim.contacts.get_contact(account, jid) and not pm:
return return
if not contact:
# contact is not in the roster, create a fake one to display
# notification
contact = common.contacts.Contact(jid = jid, resource = resource)
advanced_notif_num = notify.get_advanced_notification('message_received', advanced_notif_num = notify.get_advanced_notification('message_received',
account, contact) account, contact)
@ -606,7 +609,7 @@ class Interface:
msg = message msg = message
if subject: if subject:
msg = _('Subject: %s') % subject + '\n' + msg msg = _('Subject: %s') % subject + '\n' + msg
notify.notify('new_message', jid, account, [msg_type, first, nickname, notify.notify('new_message', full_jid_with_resource, account, [msg_type, first, nickname,
msg], advanced_notif_num) msg], advanced_notif_num)
if self.remote_ctrl: if self.remote_ctrl:
@ -851,6 +854,7 @@ class Interface:
self.remote_ctrl.raise_signal('LastStatusTime', (account, array)) self.remote_ctrl.raise_signal('LastStatusTime', (account, array))
def handle_event_os_info(self, account, array): def handle_event_os_info(self, account, array):
#'OS_INFO' (account, (jid, resource, client_info, os_info))
win = None win = None
if self.instances[account]['infos'].has_key(array[0]): if self.instances[account]['infos'].has_key(array[0]):
win = self.instances[account]['infos'][array[0]] win = self.instances[account]['infos'][array[0]]
@ -1075,7 +1079,7 @@ class Interface:
gmail_messages_list = array[2] gmail_messages_list = array[2]
if gajim.config.get('notify_on_new_gmail_email'): if gajim.config.get('notify_on_new_gmail_email'):
img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
'single_msg_recv.png') #FIXME: find a better image 'new_email_recv.png')
title = _('New E-mail on %(gmail_mail_address)s') % \ title = _('New E-mail on %(gmail_mail_address)s') % \
{'gmail_mail_address': jid} {'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 E-mail message', 'You have %d new E-mail messages', gmail_new_messages, gmail_new_messages, gmail_new_messages)
@ -1328,7 +1332,9 @@ class Interface:
self.instances[account]['xml_console'].print_stanza(stanza, 'outgoing') self.instances[account]['xml_console'].print_stanza(stanza, 'outgoing')
def handle_event_vcard_published(self, account, array): def handle_event_vcard_published(self, account, array):
dialogs.InformationDialog(_('vCard publication succeeded'), _('Your personal information has been published successfully.')) if self.instances[account].has_key('profile'):
win = self.instances[account]['profile']
win.vcard_published()
for gc_control in self.msg_win_mgr.get_controls(message_control.TYPE_GC): for gc_control in self.msg_win_mgr.get_controls(message_control.TYPE_GC):
if gc_control.account == account: if gc_control.account == account:
show = gajim.SHOW_LIST[gajim.connections[account].connected] show = gajim.SHOW_LIST[gajim.connections[account].connected]
@ -1337,7 +1343,9 @@ class Interface:
gc_control.room_jid, show, status) gc_control.room_jid, show, status)
def handle_event_vcard_not_published(self, account, array): def handle_event_vcard_not_published(self, account, array):
dialogs.InformationDialog(_('vCard publication failed'), _('There was an error while publishing your personal information, try again later.')) if self.instances[account].has_key('profile'):
win = self.instances[account]['profile']
win.vcard_not_published()
def handle_event_signed_in(self, account, empty): def handle_event_signed_in(self, account, empty):
'''SIGNED_IN event is emitted when we sign in, so handle it''' '''SIGNED_IN event is emitted when we sign in, so handle it'''
@ -1406,10 +1414,10 @@ class Interface:
if response == gtk.RESPONSE_OK: if response == gtk.RESPONSE_OK:
new_name = dlg.input_entry.get_text() new_name = dlg.input_entry.get_text()
print 'account, data', account, data, new_name print 'account, data', account, data, new_name
gajim.config.set_per('accounts', gajim.LOCAL_ACC, 'name', new_name) gajim.config.set_per('accounts', account, 'name', new_name)
status = gajim.connections[account].status status = gajim.connections[account].status
print 'status', status gajim.connections[account].username = new_name
gajim.connections[account].reconnect() gajim.connections[account].change_status(status, '')
def read_sleepy(self): def read_sleepy(self):
@ -1744,14 +1752,17 @@ class Interface:
jid = gajim.get_jid_without_resource(jid) jid = gajim.get_jid_without_resource(jid)
if type_ in ('printed_gc_msg', 'gc_msg'): if type_ in ('printed_gc_msg', 'gc_msg'):
w = self.msg_win_mgr.get_window(jid, account) w = self.msg_win_mgr.get_window(jid, account)
elif type_ in ('printed_chat', 'chat'): elif type_ in ('printed_chat', 'chat', ''):
# '' is for log in/out notifications
if self.msg_win_mgr.has_window(fjid, account): if self.msg_win_mgr.has_window(fjid, account):
w = self.msg_win_mgr.get_window(fjid, account) w = self.msg_win_mgr.get_window(fjid, account)
elif self.msg_win_mgr.has_window(jid, account):
w = self.msg_win_mgr.get_window(jid, account)
else: else:
contact = gajim.contacts.get_contact(account, jid, resource) contact = gajim.contacts.get_contact(account, jid, resource)
if isinstance(contact, list): if not contact or isinstance(contact, list):
contact = gajim.contacts.get_first_contact_from_jid(account, jid) contact = gajim.contacts.get_first_contact_from_jid(account, jid)
self.roster.new_chat(contact, account, resource = resource) self.roster.new_chat(contact, account)
w = self.msg_win_mgr.get_window(fjid, account) w = self.msg_win_mgr.get_window(fjid, account)
gajim.last_message_time[account][jid] = 0 # long time ago gajim.last_message_time[account][jid] = 0 # long time ago
elif type_ in ('printed_pm', 'pm'): elif type_ in ('printed_pm', 'pm'):
@ -1774,9 +1785,15 @@ class Interface:
elif type_ in ('normal', 'file-request', 'file-request-error', elif type_ in ('normal', 'file-request', 'file-request-error',
'file-send-error', 'file-error', 'file-stopped', 'file-completed'): 'file-send-error', 'file-error', 'file-stopped', 'file-completed'):
# Get the first single message event # Get the first single message event
event = gajim.events.get_first_event(account, fjid, type_)
if not event:
# default to jid without resource
event = gajim.events.get_first_event(account, jid, type_) event = gajim.events.get_first_event(account, jid, type_)
# Open the window # Open the window
self.roster.open_event(account, jid, event) self.roster.open_event(account, jid, event)
else:
# Open the window
self.roster.open_event(account, fjid, event)
elif type_ == 'gmail': elif type_ == 'gmail':
if gajim.config.get_per('accounts', account, 'savepass'): if gajim.config.get_per('accounts', account, 'savepass'):
url = ('http://www.google.com/accounts/ServiceLoginAuth?service=mail&Email=%s&Passwd=%s&continue=https://mail.google.com/mail') %\ url = ('http://www.google.com/accounts/ServiceLoginAuth?service=mail&Email=%s&Passwd=%s&continue=https://mail.google.com/mail') %\
@ -1874,8 +1891,11 @@ class Interface:
if account != gajim.ZEROCONF_ACC_NAME: if account != gajim.ZEROCONF_ACC_NAME:
gajim.connections[account] = common.connection.Connection(account) gajim.connections[account] = common.connection.Connection(account)
# gtk hooks
gtk.about_dialog_set_email_hook(self.on_launch_browser_mailer, 'mail') gtk.about_dialog_set_email_hook(self.on_launch_browser_mailer, 'mail')
gtk.about_dialog_set_url_hook(self.on_launch_browser_mailer, 'url') gtk.about_dialog_set_url_hook(self.on_launch_browser_mailer, 'url')
if gtk.pygtk_version >= (2, 10, 0) and gtk.gtk_version >= (2, 10, 0):
gtk.link_button_set_uri_hook(self.on_launch_browser_mailer, 'url')
self.instances = {'logs': {}} self.instances = {'logs': {}}
@ -1919,6 +1939,8 @@ class Interface:
self.systray_capabilities = False self.systray_capabilities = False
if os.name == 'nt': if os.name == 'nt':
pass
'''
try: try:
import systraywin32 import systraywin32
except: # user doesn't have trayicon capabilities except: # user doesn't have trayicon capabilities
@ -1926,6 +1948,7 @@ class Interface:
else: else:
self.systray_capabilities = True self.systray_capabilities = True
self.systray = systraywin32.SystrayWin32() self.systray = systraywin32.SystrayWin32()
'''
else: else:
self.systray_capabilities = systray.HAS_SYSTRAY_CAPABILITIES self.systray_capabilities = systray.HAS_SYSTRAY_CAPABILITIES
if self.systray_capabilities: if self.systray_capabilities:

View file

@ -51,7 +51,7 @@ class GajimThemesWindow:
self.themes_tree = self.xml.get_widget('themes_treeview') self.themes_tree = self.xml.get_widget('themes_treeview')
self.theme_options_vbox = self.xml.get_widget('theme_options_vbox') self.theme_options_vbox = self.xml.get_widget('theme_options_vbox')
self.colorbuttons = {} self.colorbuttons = {}
for chatstate in ('active', 'inactive', 'composing', 'paused', 'gone', for chatstate in ('inactive', 'composing', 'paused', 'gone',
'muc_msg', 'muc_directed_msg'): 'muc_msg', 'muc_directed_msg'):
self.colorbuttons[chatstate] = self.xml.get_widget(chatstate + \ self.colorbuttons[chatstate] = self.xml.get_widget(chatstate + \
'_colorbutton') '_colorbutton')
@ -198,7 +198,7 @@ class GajimThemesWindow:
self.no_update = False self.no_update = False
gajim.interface.roster.change_roster_style(None) gajim.interface.roster.change_roster_style(None)
for chatstate in ('active', 'inactive', 'composing', 'paused', 'gone', for chatstate in ('inactive', 'composing', 'paused', 'gone',
'muc_msg', 'muc_directed_msg'): 'muc_msg', 'muc_directed_msg'):
color = gajim.config.get_per('themes', theme, 'state_' + chatstate + \ color = gajim.config.get_per('themes', theme, 'state_' + chatstate + \
'_color') '_color')
@ -333,11 +333,6 @@ class GajimThemesWindow:
font_props[1] = True font_props[1] = True
return font_props return font_props
def on_active_colorbutton_color_set(self, widget):
self.no_update = True
self._set_color(True, widget, 'state_active_color')
self.no_update = False
def on_inactive_colorbutton_color_set(self, widget): def on_inactive_colorbutton_color_set(self, widget):
self.no_update = True self.no_update = True
self._set_color(True, widget, 'state_inactive_color') self._set_color(True, widget, 'state_inactive_color')

View file

@ -226,9 +226,6 @@ class GroupchatControl(ChatControlBase):
self.gc_popup_menu = xm.get_widget('gc_control_popup_menu') self.gc_popup_menu = xm.get_widget('gc_control_popup_menu')
self.name_label = self.xml.get_widget('banner_name_label') self.name_label = self.xml.get_widget('banner_name_label')
id = self.parent_win.window.connect('focus-in-event',
self._on_window_focus_in_event)
self.handlers[id] = self.parent_win.window
# set the position of the current hpaned # set the position of the current hpaned
self.hpaned_position = gajim.config.get('gc-hpaned-position') self.hpaned_position = gajim.config.get('gc-hpaned-position')
@ -320,11 +317,6 @@ class GroupchatControl(ChatControlBase):
return gajim.config.get('notify_on_all_muc_messages') or \ return gajim.config.get('notify_on_all_muc_messages') or \
self.attention_flag self.attention_flag
def _on_window_focus_in_event(self, widget, event):
'''When window gets focus'''
if self.parent_win.get_active_jid() == self.room_jid:
self.conv_textview.allow_focus_out_line = True
def on_treeview_size_allocate(self, widget, allocation): def on_treeview_size_allocate(self, widget, allocation):
'''The MUC treeview has resized. Move the hpaned in all tabs to match''' '''The MUC treeview has resized. Move the hpaned in all tabs to match'''
self.hpaned_position = self.hpaned.get_position() self.hpaned_position = self.hpaned.get_position()
@ -371,22 +363,23 @@ class GroupchatControl(ChatControlBase):
has_focus = self.parent_win.window.get_property('has-toplevel-focus') has_focus = self.parent_win.window.get_property('has-toplevel-focus')
current_tab = self.parent_win.get_active_control() == self current_tab = self.parent_win.get_active_control() == self
color_name = None
color = None color = None
theme = gajim.config.get('roster_theme') theme = gajim.config.get('roster_theme')
if chatstate == 'attention' and (not has_focus or not current_tab): if chatstate == 'attention' and (not has_focus or not current_tab):
self.attention_flag = True self.attention_flag = True
color = gajim.config.get_per('themes', theme, color_name = gajim.config.get_per('themes', theme,
'state_muc_directed_msg_color') 'state_muc_directed_msg_color')
elif chatstate: elif chatstate:
if chatstate == 'active' or (current_tab and has_focus): if chatstate == 'active' or (current_tab and has_focus):
self.attention_flag = False self.attention_flag = False
color = gajim.config.get_per('themes', theme, # get active color from gtk
'state_active_color') color = self.parent_win.notebook.style.fg[gtk.STATE_ACTIVE]
elif chatstate == 'newmsg' and (not has_focus or not current_tab) and\ elif chatstate == 'newmsg' and (not has_focus or not current_tab) and\
not self.attention_flag: not self.attention_flag:
color = gajim.config.get_per('themes', theme, 'state_muc_msg_color') color_name = gajim.config.get_per('themes', theme, 'state_muc_msg_color')
if color: if color_name:
color = gtk.gdk.colormap_get_system().alloc_color(color) color = gtk.gdk.colormap_get_system().alloc_color(color_name)
label_str = self.name label_str = self.name
return (label_str, color) return (label_str, color)
@ -865,7 +858,9 @@ class GroupchatControl(ChatControlBase):
print_status = gajim.config.get('print_status_in_muc') print_status = gajim.config.get('print_status_in_muc')
nick_jid = nick nick_jid = nick
if jid: if jid:
nick_jid += ' (%s)' % jid # delete ressource
simple_jid = gajim.get_jid_without_resource(jid)
nick_jid += ' (%s)' % simple_jid
if show == 'offline' and print_status in ('all', 'in_and_out'): if show == 'offline' and print_status in ('all', 'in_and_out'):
st = _('%s has left') % nick_jid st = _('%s has left') % nick_jid
if reason: if reason:
@ -1268,6 +1263,10 @@ class GroupchatControl(ChatControlBase):
del self.handlers[i] del self.handlers[i]
def allow_shutdown(self): def allow_shutdown(self):
model, iter = self.list_treeview.get_selection().get_selected()
if iter:
self.list_treeview.get_selection().unselect_all()
return False
retval = True retval = True
includes = gajim.config.get('confirm_close_muc_rooms').split(' ') includes = gajim.config.get('confirm_close_muc_rooms').split(' ')
excludes = gajim.config.get('noconfirm_close_muc_rooms').split(' ') excludes = gajim.config.get('noconfirm_close_muc_rooms').split(' ')
@ -1293,6 +1292,7 @@ class GroupchatControl(ChatControlBase):
return retval return retval
def set_control_active(self, state): def set_control_active(self, state):
self.conv_textview.allow_focus_out_line = True
self.attention_flag = False self.attention_flag = False
ChatControlBase.set_control_active(self, state) ChatControlBase.set_control_active(self, state)
if not state: if not state:
@ -1453,7 +1453,11 @@ class GroupchatControl(ChatControlBase):
def on_list_treeview_key_press_event(self, widget, event): def on_list_treeview_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape: if event.keyval == gtk.keysyms.Escape:
selection = widget.get_selection()
model, iter = selection.get_selected()
if iter:
widget.get_selection().unselect_all() widget.get_selection().unselect_all()
return True
def on_list_treeview_row_expanded(self, widget, iter, path): def on_list_treeview_row_expanded(self, widget, iter, path):
'''When a row is expanded: change the icon of the arrow''' '''When a row is expanded: change the icon of the arrow'''

View file

@ -390,7 +390,7 @@ def possibly_move_window_in_current_desktop(window):
current virtual desktop current virtual desktop
window is GTK window''' window is GTK window'''
if os.name == 'nt': if os.name == 'nt':
return return False
root_window = gtk.gdk.screen_get_default().get_root_window() root_window = gtk.gdk.screen_get_default().get_root_window()
# current user's vd # current user's vd
@ -406,6 +406,8 @@ def possibly_move_window_in_current_desktop(window):
# we are in another VD that the window was # we are in another VD that the window was
# so show it in current VD # so show it in current VD
window.present() window.present()
return True
return False
def file_is_locked(path_to_file): def file_is_locked(path_to_file):
'''returns True if file is locked (WINDOWS ONLY)''' '''returns True if file is locked (WINDOWS ONLY)'''
@ -680,6 +682,14 @@ default_name = ''):
file_path = dialog.get_filename() file_path = dialog.get_filename()
file_path = decode_filechooser_file_paths((file_path,))[0] file_path = decode_filechooser_file_paths((file_path,))[0]
if os.path.exists(file_path): if os.path.exists(file_path):
# check if we have write permissions
if not os.access(file_path, os.W_OK):
file_name = os.path.basename(file_path)
dialogs.ErrorDialog(_('Cannot overwrite existing file "%s"' %
file_name),
_('A file with this name already exists and you do not have '
'permission to overwrite it.'))
return
dialog2 = dialogs.FTOverwriteConfirmationDialog( dialog2 = dialogs.FTOverwriteConfirmationDialog(
_('This file already exists'), _('What do you want to do?'), _('This file already exists'), _('What do you want to do?'),
False) False)
@ -688,6 +698,13 @@ default_name = ''):
response = dialog2.get_response() response = dialog2.get_response()
if response < 0: if response < 0:
return return
else:
dirname = os.path.dirname(file_path)
if not os.access(dirname, os.W_OK):
dialogs.ErrorDialog(_('Directory "%s" is not writable') % \
dirname, _('You do not have permission to create files in this'
' directory.'))
return
# Get pixbuf # Get pixbuf
pixbuf = None pixbuf = None
@ -710,7 +727,7 @@ default_name = ''):
try: try:
pixbuf.save(file_path, type_) pixbuf.save(file_path, type_)
except: except:
#XXX Check for permissions if os.path.exists(file_path):
os.remove(file_path) os.remove(file_path)
new_file_path = '.'.join(file_path.split('.')[:-1]) + '.jpeg' new_file_path = '.'.join(file_path.split('.')[:-1]) + '.jpeg'
dialog2 = dialogs.ConfirmationDialog(_('Extension not supported'), dialog2 = dialogs.ConfirmationDialog(_('Extension not supported'),
@ -735,3 +752,6 @@ default_name = ''):
dialog.set_current_name(default_name) dialog.set_current_name(default_name)
dialog.connect('delete-event', lambda widget, event: dialog.connect('delete-event', lambda widget, event:
on_cancel(widget)) on_cancel(widget))
def on_bm_header_changed_state(widget, event):
widget.set_state(gtk.STATE_NORMAL) #do not allow selected_state

View file

@ -104,6 +104,16 @@ class MessageWindow:
self.notebook.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.DND_TARGETS, self.notebook.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.DND_TARGETS,
gtk.gdk.ACTION_MOVE) gtk.gdk.ACTION_MOVE)
def change_account_name(self, old_name, new_name):
if self._controls.has_key(old_name):
self._controls[new_name] = self._controls[old_name]
del self._controls[old_name]
for ctrl in self.controls():
if ctrl.account == old_name:
ctrl.account = new_name
if self.account == old_name:
self.account = new_name
def get_num_controls(self): def get_num_controls(self):
n = 0 n = 0
for dict in self._controls.values(): for dict in self._controls.values():
@ -619,6 +629,10 @@ class MessageWindowMgr:
mode = gajim.config.get('one_message_window') mode = gajim.config.get('one_message_window')
self.mode = common.config.opt_one_window_types.index(mode) self.mode = common.config.opt_one_window_types.index(mode)
def change_account_name(self, old_name, new_name):
for win in self.windows():
win.change_account_name(old_name, new_name)
def _new_window(self, acct, type): def _new_window(self, acct, type):
win = MessageWindow(acct, type) win = MessageWindow(acct, type)
# we track the lifetime of this window # we track the lifetime of this window

118
src/music_track_listener.py Normal file
View file

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
## musictracklistener.py
##
## Copyright (C) 2006 Gustavo 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.
##
import gobject
import dbus_support
if dbus_support.supported:
import dbus
import dbus.glib
class MusicTrackInfo(object):
__slots__ = ['title', 'album', 'artist', 'duration', 'track_number']
class MusicTrackListener(gobject.GObject):
__gsignals__ = { 'music-track-changed': (gobject.SIGNAL_RUN_LAST, None,
(object,)) }
_instance = None
@classmethod
def get(cls):
if cls._instance is None:
cls._instance = cls()
return cls._instance
def __init__(self):
super(MusicTrackListener, self).__init__()
bus = dbus.SessionBus()
bus.add_signal_receiver(self._muine_music_track_change_cb, 'SongChanged',
'org.gnome.Muine.Player')
bus.add_signal_receiver(self._rhythmbox_music_track_change_cb,
'playingUriChanged', 'org.gnome.Rhythmbox.Player')
def _muine_properties_extract(self, song_string):
d = dict((x.strip() for x in s1.split(':', 1)) for s1 in song_string.split('\n'))
info = MusicTrackInfo()
info.title = d['title']
info.album = d['album']
info.artist = d['artist']
info.duration = int(d['duration'])
info.track_number = int(d['track_number'])
return info
def _muine_music_track_change_cb(self, arg):
info = self._muine_properties_extract(arg)
self.emit('music-track-changed', info)
def _rhythmbox_properties_extract(self, props):
info = MusicTrackInfo()
info.title = props['title']
info.album = props['album']
info.artist = props['artist']
info.duration = int(props['duration'])
info.track_number = int(props['track-number'])
return info
def _rhythmbox_music_track_change_cb(self, uri):
bus = dbus.SessionBus()
rbshellobj = bus.get_object('org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Shell')
rbshell = dbus.Interface(rbshellobj, 'org.gnome.Rhythmbox.Shell')
props = rbshell.getSongProperties(uri)
info = self._rhythmbox_properties_extract(props)
self.emit('music-track-changed', info)
def get_playing_track(self):
'''Return a MusicTrackInfo for the currently playing
song, or None if no song is playing'''
bus = dbus.SessionBus()
## Check Muine playing track
if dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
'org.gnome.Muine'):
obj = bus.get_object('org.gnome.Muine', '/org/gnome/Muine/Player')
player = dbus.Interface(obj, 'org.gnome.Muine.Player')
if player.GetPlaying():
song_string = player.GetCurrentSong()
song = self._muine_properties_extract(song_string)
return song
## Check Rhythmbox playing song
if dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
'org.gnome.Rhythmbox'):
rbshellobj = bus.get_object('org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Shell')
player = dbus.Interface(
bus.get_object('org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Player'),
'org.gnome.Rhythmbox.Player')
rbshell = dbus.Interface(rbshellobj, 'org.gnome.Rhythmbox.Shell')
uri = player.getPlayingUri()
props = rbshell.getSongProperties(uri)
info = self._rhythmbox_properties_extract(props)
return info
return None
# here we test :)
if __name__ == '__main__':
def music_track_change_cb(listener, music_track_info):
print music_track_info.title
listener = MusicTrackListener.get()
listener.connect('music-track-changed', music_track_change_cb)
track = listener.get_playing_track()
if track is None:
print 'Now not playing anything'
else:
print 'Now playing: "%s" by %s' % (track.title, track.artist)
gobject.MainLoop().run()

View file

@ -28,7 +28,6 @@ from common import helpers
import dbus_support import dbus_support
if dbus_support.supported: if dbus_support.supported:
import dbus import dbus
if dbus_support.version >= (0, 41, 0):
import dbus.glib import dbus.glib
import dbus.service import dbus.service
@ -42,11 +41,9 @@ def get_show_in_roster(event, account, contact):
return False return False
if event == 'message_received': if event == 'message_received':
chat_control = helpers.get_chat_control(account, contact) chat_control = helpers.get_chat_control(account, contact)
if not chat_control: if chat_control:
return True
elif event == 'ft_request':
return True
return False return False
return True
def get_show_in_systray(event, account, contact): def get_show_in_systray(event, account, contact):
'''Return True if this event must be shown in roster, else False''' '''Return True if this event must be shown in roster, else False'''
@ -56,10 +53,7 @@ def get_show_in_systray(event, account, contact):
return True return True
if gajim.config.get_per('notifications', str(num), 'systray') == 'no': if gajim.config.get_per('notifications', str(num), 'systray') == 'no':
return False return False
if event in ('message_received', 'ft_request', 'gc_msg_highlight',
'ft_request'):
return True return True
return False
def get_advanced_notification(event, account, contact): def get_advanced_notification(event, account, contact):
'''Returns the number of the first advanced notification or None''' '''Returns the number of the first advanced notification or None'''

View file

@ -60,17 +60,40 @@ class ProfileWindow:
def __init__(self, account): def __init__(self, account):
self.xml = gtkgui_helpers.get_glade('profile_window.glade') self.xml = gtkgui_helpers.get_glade('profile_window.glade')
self.window = self.xml.get_widget('profile_window') self.window = self.xml.get_widget('profile_window')
self.progressbar = self.xml.get_widget('progressbar')
self.statusbar = self.xml.get_widget('statusbar')
self.context_id = self.statusbar.get_context_id('profile')
self.account = account self.account = account
self.jid = gajim.get_jid_from_account(account) self.jid = gajim.get_jid_from_account(account)
self.avatar_mime_type = None self.avatar_mime_type = None
self.avatar_encoded = None self.avatar_encoded = None
self.message_id = self.statusbar.push(self.context_id,
_('Retrieving profile...'))
self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar)
self.remove_statusbar_timeout_id = None
# Create Image for avatar button
image = gtk.Image()
self.xml.get_widget('PHOTO_button').set_image(image)
self.xml.signal_autoconnect(self) self.xml.signal_autoconnect(self)
self.window.show_all() self.window.show_all()
def update_progressbar(self):
self.progressbar.pulse()
return True # loop forever
def remove_statusbar(self, message_id):
self.statusbar.remove(self.context_id, message_id)
self.remove_statusbar_timeout_id = None
def on_profile_window_destroy(self, widget): def on_profile_window_destroy(self, widget):
if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id)
if self.remove_statusbar_timeout_id is not None:
gobject.source_remove(self.remove_statusbar_timeout_id)
del gajim.interface.instances[self.account]['profile'] del gajim.interface.instances[self.account]['profile']
def on_profile_window_key_press_event(self, widget, event): def on_profile_window_key_press_event(self, widget, event):
@ -79,8 +102,10 @@ class ProfileWindow:
def on_clear_button_clicked(self, widget): def on_clear_button_clicked(self, widget):
# empty the image # empty the image
self.xml.get_widget('PHOTO_image').set_from_icon_name('stock_person', button = self.xml.get_widget('PHOTO_button')
gtk.ICON_SIZE_DIALOG) image = button.get_image()
image.set_from_pixbuf(None)
button.set_label(_('Click to set your avatar'))
self.avatar_encoded = None self.avatar_encoded = None
self.avatar_mime_type = None self.avatar_mime_type = None
@ -124,18 +149,33 @@ class ProfileWindow:
pixbuf = gtkgui_helpers.get_pixbuf_from_data(data) pixbuf = gtkgui_helpers.get_pixbuf_from_data(data)
# rescale it # rescale it
pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard') pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard')
image = self.xml.get_widget('PHOTO_image') button = self.xml.get_widget('PHOTO_button')
image = button.get_image()
image.set_from_pixbuf(pixbuf) image.set_from_pixbuf(pixbuf)
button.set_label('')
self.avatar_encoded = base64.encodestring(data) self.avatar_encoded = base64.encodestring(data)
# returns None if unknown type # returns None if unknown type
self.avatar_mime_type = mimetypes.guess_type(path_to_file)[0] self.avatar_mime_type = mimetypes.guess_type(path_to_file)[0]
self.dialog = dialogs.ImageChooserDialog(on_response_ok = on_ok) def on_clear(widget):
self.dialog.destroy()
self.on_clear_button_clicked(widget)
self.dialog = dialogs.AvatarChooserDialog(on_response_ok = on_ok,
on_response_clear = on_clear)
def on_PHOTO_button_press_event(self, widget, event): def on_PHOTO_button_press_event(self, widget, event):
'''If right-clicked, show popup''' '''If right-clicked, show popup'''
if event.button == 3 and self.avatar_encoded: # right click if event.button == 3 and self.avatar_encoded: # right click
menu = gtk.Menu() menu = gtk.Menu()
# Try to get pixbuf
is_fake = False
if account and gajim.contacts.is_pm_from_jid(account, jid):
is_fake = True
pixbuf = get_avatar_pixbuf_from_cache(jid, is_fake)
if pixbuf:
nick = gajim.config.get_per('accounts', self.account, 'name') nick = gajim.config.get_per('accounts', self.account, 'name')
menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS) menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS)
menuitem.connect('activate', menuitem.connect('activate',
@ -162,18 +202,23 @@ class ProfileWindow:
def set_values(self, vcard): def set_values(self, vcard):
if not 'PHOTO' in vcard: if not 'PHOTO' in vcard:
# set default image # set default image
image = self.xml.get_widget('PHOTO_image') button = self.xml.get_widget('PHOTO_button')
image.set_from_icon_name('stock_person', gtk.ICON_SIZE_DIALOG) image = button.get_image()
image.set_from_pixbuf(None)
button.set_label(_('Click to set your avatar'))
for i in vcard.keys(): for i in vcard.keys():
if i == 'PHOTO': if i == 'PHOTO':
pixbuf, self.avatar_encoded, self.avatar_mime_type = \ pixbuf, self.avatar_encoded, self.avatar_mime_type = \
get_avatar_pixbuf_encoded_mime(vcard[i]) get_avatar_pixbuf_encoded_mime(vcard[i])
image = self.xml.get_widget('PHOTO_image') button = self.xml.get_widget('PHOTO_button')
image = button.get_image()
if not pixbuf: if not pixbuf:
image.set_from_icon_name('stock_person', gtk.ICON_SIZE_DIALOG) image.set_from_pixbuf(None)
button.set_label(_('Click to set your avatar'))
continue continue
pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard') pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard')
image.set_from_pixbuf(pixbuf) image.set_from_pixbuf(pixbuf)
button.set_label('')
continue continue
if i == 'ADR' or i == 'TEL' or i == 'EMAIL': if i == 'ADR' or i == 'TEL' or i == 'EMAIL':
for entry in vcard[i]: for entry in vcard[i]:
@ -191,6 +236,18 @@ class ProfileWindow:
vcard[i], 0) vcard[i], 0)
else: else:
self.set_value(i + '_entry', vcard[i]) self.set_value(i + '_entry', vcard[i])
if self.update_progressbar_timeout_id is not None:
if self.message_id:
self.statusbar.remove(self.context_id, self.message_id)
self.message_id = self.statusbar.push(self.context_id,
_('Information received'))
self.remove_statusbar_timeout_id = gobject.timeout_add(3000,
self.remove_statusbar, self.message_id)
gobject.source_remove(self.update_progressbar_timeout_id)
# redraw progressbar after avatar is set so that windows is already
# resized. Else progressbar is not correctly redrawn
gobject.idle_add(self.progressbar.set_fraction, 0)
self.update_progressbar_timeout_id = None
def add_to_vcard(self, vcard, entry, txt): def add_to_vcard(self, vcard, entry, txt):
'''Add an information to the vCard dictionary''' '''Add an information to the vCard dictionary'''
@ -248,6 +305,9 @@ class ProfileWindow:
return vcard return vcard
def on_publish_button_clicked(self, widget): def on_publish_button_clicked(self, widget):
if self.update_progressbar_timeout_id:
# Operation in progress
return
if gajim.connections[self.account].connected < 2: if gajim.connections[self.account].connected < 2:
dialogs.ErrorDialog(_('You are not connected to the server'), dialogs.ErrorDialog(_('You are not connected to the server'),
_('Without a connection you can not publish your contact ' _('Without a connection you can not publish your contact '
@ -261,8 +321,42 @@ class ProfileWindow:
nick = gajim.config.get_per('accounts', self.account, 'name') nick = gajim.config.get_per('accounts', self.account, 'name')
gajim.nicks[self.account] = nick gajim.nicks[self.account] = nick
gajim.connections[self.account].send_vcard(vcard) gajim.connections[self.account].send_vcard(vcard)
self.message_id = self.statusbar.push(self.context_id,
_('Sending profile...'))
self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar)
def vcard_published(self):
if self.message_id:
self.statusbar.remove(self.context_id, self.message_id)
self.message_id = self.statusbar.push(self.context_id,
_('Information published'))
self.remove_statusbar_timeout_id = gobject.timeout_add(3000,
self.remove_statusbar, self.message_id)
if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id)
self.progressbar.set_fraction(0)
self.update_progressbar_timeout_id = None
def vcard_not_published(self):
if self.message_id:
self.statusbar.remove(self.context_id, self.message_id)
self.message_id = self.statusbar.push(self.context_id,
_('Information NOT published'))
self.remove_statusbar_timeout_id = gobject.timeout_add(3000,
self.remove_statusbar, self.message_id)
if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id)
self.progressbar.set_fraction(0)
self.update_progressbar_timeout_id = None
dialogs.InformationDialog(_('vCard publication failed'),
_('There was an error while publishing your personal information, '
'try again later.'))
def on_retrieve_button_clicked(self, widget): def on_retrieve_button_clicked(self, widget):
if self.update_progressbar_timeout_id:
# Operation in progress
return
entries = ['FN', 'NICKNAME', 'BDAY', 'EMAIL_HOME_USERID', 'URL', entries = ['FN', 'NICKNAME', 'BDAY', 'EMAIL_HOME_USERID', 'URL',
'TEL_HOME_NUMBER', 'N_FAMILY', 'N_GIVEN', 'N_MIDDLE', 'N_PREFIX', 'TEL_HOME_NUMBER', 'N_FAMILY', 'N_GIVEN', 'N_MIDDLE', 'N_PREFIX',
'N_SUFFIX', 'ADR_HOME_STREET', 'ADR_HOME_EXTADR', 'ADR_HOME_LOCALITY', 'N_SUFFIX', 'ADR_HOME_STREET', 'ADR_HOME_EXTADR', 'ADR_HOME_LOCALITY',
@ -275,9 +369,18 @@ class ProfileWindow:
for e in entries: for e in entries:
self.xml.get_widget(e + '_entry').set_text('') self.xml.get_widget(e + '_entry').set_text('')
self.xml.get_widget('DESC_textview').get_buffer().set_text('') self.xml.get_widget('DESC_textview').get_buffer().set_text('')
self.xml.get_widget('PHOTO_image').set_from_icon_name('stock_person', button = self.xml.get_widget('PHOTO_button')
gtk.ICON_SIZE_DIALOG) image = button.get_image()
image.set_from_pixbuf(None)
button.set_label(_('Click to set your avatar'))
gajim.connections[self.account].request_vcard(self.jid) gajim.connections[self.account].request_vcard(self.jid)
else: else:
dialogs.ErrorDialog(_('You are not connected to the server'), dialogs.ErrorDialog(_('You are not connected to the server'),
_('Without a connection, you can not get your contact information.')) _('Without a connection, you can not get your contact information.'))
self.message_id = self.statusbar.push(self.context_id,
_('Retrieving profile...'))
self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar)
def on_close_button_clicked(self, widget):
self.window.destroy()

View file

@ -1,19 +1,9 @@
## remote_control.py ## remote_control.py
## ##
## Contributors for this file: ## Copyright (C) 2005-2006 Yann Le Boulanger <asterix@lagaule.org>
## - Yann Le Boulanger <asterix@lagaule.org> ## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
## - Nikos Kouremenos <kourem@gmail.com> ## Copyright (C) 2005-2006 Dimitur Kirov <dkirov@gmail.com>
## - Dimitur Kirov <dkirov@gmail.com> ## Copyright (C) 2005-2006 Andrew Sayman <lorien420@myrealbox.com>
## - Andrew Sayman <lorien420@myrealbox.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 <nkour@jabber.org>
## Dimitur Kirov <dkirov@gmail.com>
## Travis Shirk <travis@pobox.com>
## Norman Rasmussen <norman@rasmussen.co.za>
## ##
## This program is free software; you can redistribute it and/or modify ## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published ## it under the terms of the GNU General Public License as published
@ -36,27 +26,20 @@ from dialogs import AddNewContactWindow, NewChatDialog
import dbus_support import dbus_support
if dbus_support.supported: if dbus_support.supported:
import dbus import dbus
if dbus_support.version >= (0, 41, 0): if dbus_support:
import dbus.service import dbus.service
import dbus.glib # cause dbus 0.35+ doesn't return signal replies without it import dbus.glib
DbusPrototype = dbus.service.Object
elif dbus_support.version >= (0, 20, 0):
DbusPrototype = dbus.Object
else: #dbus is not defined
DbusPrototype = str
INTERFACE = 'org.gajim.dbus.RemoteInterface' INTERFACE = 'org.gajim.dbus.RemoteInterface'
OBJ_PATH = '/org/gajim/dbus/RemoteObject' OBJ_PATH = '/org/gajim/dbus/RemoteObject'
SERVICE = 'org.gajim.dbus' SERVICE = 'org.gajim.dbus'
# type mapping, it is different in each version # type mapping
ident = lambda e: e
if dbus_support.version[1] >= 43:
# in most cases it is a utf-8 string # in most cases it is a utf-8 string
DBUS_STRING = dbus.String DBUS_STRING = dbus.String
# general type (for use in dicts, # general type (for use in dicts, where all values should have the same type)
# where all values should have the same type)
DBUS_VARIANT = dbus.Variant DBUS_VARIANT = dbus.Variant
DBUS_BOOLEAN = dbus.Boolean DBUS_BOOLEAN = dbus.Boolean
DBUS_DOUBLE = dbus.Double DBUS_DOUBLE = dbus.Double
@ -68,26 +51,6 @@ if dbus_support.version[1] >= 43:
# empty type # empty type
DBUS_NONE = lambda : dbus.Variant(0) DBUS_NONE = lambda : dbus.Variant(0)
else: # 33, 35, 36
DBUS_DICT_SV = lambda : {}
DBUS_DICT_SS = lambda : {}
DBUS_STRING = lambda e: unicode(e).encode('utf-8')
# this is the only way to return lists and dicts of mixed types
DBUS_VARIANT = lambda e: (isinstance(e, (str, unicode)) and \
DBUS_STRING(e)) or repr(e)
DBUS_NONE = lambda : ''
if dbus_support.version[1] >= 41: # 35, 36
DBUS_BOOLEAN = dbus.Boolean
DBUS_DOUBLE = dbus.Double
DBUS_INT32 = dbus.Int32
else: # 33
DBUS_BOOLEAN = ident
DBUS_INT32 = ident
DBUS_DOUBLE = ident
STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
'invisible']
def get_dbus_struct(obj): def get_dbus_struct(obj):
''' recursively go through all the items and replace ''' recursively go through all the items and replace
them with their casted dbus equivalents them with their casted dbus equivalents
@ -123,12 +86,8 @@ class Remote:
self.signal_object = None self.signal_object = None
session_bus = dbus_support.session_bus.SessionBus() session_bus = dbus_support.session_bus.SessionBus()
if dbus_support.version[1] >= 41:
service = dbus.service.BusName(SERVICE, bus=session_bus) service = dbus.service.BusName(SERVICE, bus=session_bus)
self.signal_object = SignalObject(service) self.signal_object = SignalObject(service)
elif dbus_support.version[1] <= 40 and dbus_support.version[1] >= 20:
service=dbus.Service(SERVICE, session_bus)
self.signal_object = SignalObject(service)
def raise_signal(self, signal, arg): def raise_signal(self, signal, arg):
if self.signal_object: if self.signal_object:
@ -136,43 +95,16 @@ class Remote:
get_dbus_struct(arg)) get_dbus_struct(arg))
class SignalObject(DbusPrototype): class SignalObject(dbus.service.Object):
''' Local object definition for /org/gajim/dbus/RemoteObject. This doc must ''' Local object definition for /org/gajim/dbus/RemoteObject.
not be visible, because the clients can access only the remote object. ''' (This docstring is not be visible, because the clients can access only the remote object.)'''
def __init__(self, service): def __init__(self, service):
self.first_show = True self.first_show = True
self.vcard_account = None self.vcard_account = None
# register our dbus API # register our dbus API
if dbus_support.version[1] >= 41: dbus.service.Object.__init__(self, service, OBJ_PATH)
DbusPrototype.__init__(self, service, OBJ_PATH)
elif dbus_support.version[1] >= 30:
DbusPrototype.__init__(self, OBJ_PATH, service)
else:
DbusPrototype.__init__(self, OBJ_PATH, service,
[ self.toggle_roster_appearance,
self.show_next_unread,
self.list_contacts,
self.list_accounts,
self.account_info,
self.change_status,
self.open_chat,
self.send_message,
self.send_single_message,
self.contact_info,
self.send_file,
self.prefs_list,
self.prefs_store,
self.prefs_del,
self.prefs_put,
self.add_contact,
self.remove_contact,
self.get_status,
self.get_status_message,
self.start_chat,
self.send_xml,
])
def raise_signal(self, signal, arg): def raise_signal(self, signal, arg):
'''raise a signal, with a single string message''' '''raise a signal, with a single string message'''
@ -182,6 +114,7 @@ class SignalObject(DbusPrototype):
i.append(arg) i.append(arg)
self._connection.send(message) self._connection.send(message)
@dbus.service.method(INTERFACE)
def get_status(self, *args): def get_status(self, *args):
'''get_status(account = None) '''get_status(account = None)
returns status (show to be exact) which is the global one returns status (show to be exact) which is the global one
@ -193,8 +126,9 @@ class SignalObject(DbusPrototype):
return helpers.get_global_show() return helpers.get_global_show()
# return show for the given account # return show for the given account
index = gajim.connections[account].connected index = gajim.connections[account].connected
return DBUS_STRING(STATUS_LIST[index]) return DBUS_STRING(gajim.SHOW_LIST[index])
@dbus.service.method(INTERFACE)
def get_status_message(self, *args): def get_status_message(self, *args):
'''get_status(account = None) '''get_status(account = None)
returns status which is the global one returns status which is the global one
@ -208,7 +142,7 @@ class SignalObject(DbusPrototype):
status = gajim.connections[account].status status = gajim.connections[account].status
return DBUS_STRING(status) return DBUS_STRING(status)
@dbus.service.method(INTERFACE)
def get_account_and_contact(self, account, jid): def get_account_and_contact(self, account, jid):
''' get the account (if not given) and contact instance from jid''' ''' get the account (if not given) and contact instance from jid'''
connected_account = None connected_account = None
@ -236,6 +170,7 @@ class SignalObject(DbusPrototype):
return connected_account, contact return connected_account, contact
@dbus.service.method(INTERFACE)
def send_file(self, *args): def send_file(self, *args):
'''send_file(file_path, jid, account=None) '''send_file(file_path, jid, account=None)
send file, located at 'file_path' to 'jid', using account send file, located at 'file_path' to 'jid', using account
@ -269,6 +204,7 @@ class SignalObject(DbusPrototype):
return True return True
return False return False
@dbus.service.method(INTERFACE)
def send_chat_message(self, *args): def send_chat_message(self, *args):
'''send_message(jid, message, keyID=None, account=None) '''send_message(jid, message, keyID=None, account=None)
send chat 'message' to 'jid', using account (optional) 'account'. send chat 'message' to 'jid', using account (optional) 'account'.
@ -277,6 +213,7 @@ class SignalObject(DbusPrototype):
jid = self._get_real_jid(jid, account) jid = self._get_real_jid(jid, account)
return self._send_message(jid, message, keyID, account) return self._send_message(jid, message, keyID, account)
@dbus.service.method(INTERFACE)
def send_single_message(self, *args): def send_single_message(self, *args):
'''send_single_message(jid, subject, message, keyID=None, account=None) '''send_single_message(jid, subject, message, keyID=None, account=None)
send single 'message' to 'jid', using account (optional) 'account'. send single 'message' to 'jid', using account (optional) 'account'.
@ -285,6 +222,7 @@ class SignalObject(DbusPrototype):
jid = self._get_real_jid(jid, account) jid = self._get_real_jid(jid, account)
return self._send_message(jid, message, keyID, account, type, subject) return self._send_message(jid, message, keyID, account, type, subject)
@dbus.service.method(INTERFACE)
def open_chat(self, *args): def open_chat(self, *args):
''' start_chat(jid, account=None) -> shows the tabbed window for new ''' start_chat(jid, account=None) -> shows the tabbed window for new
message to 'jid', using account(optional) 'account' ''' message to 'jid', using account(optional) 'account' '''
@ -332,6 +270,7 @@ class SignalObject(DbusPrototype):
return True return True
return False return False
@dbus.service.method(INTERFACE)
def change_status(self, *args, **keywords): def change_status(self, *args, **keywords):
''' change_status(status, message, account). account is optional - ''' change_status(status, message, account). account is optional -
if not specified status is changed for all accounts. ''' if not specified status is changed for all accounts. '''
@ -352,11 +291,13 @@ class SignalObject(DbusPrototype):
status, message) status, message)
return None return None
@dbus.service.method(INTERFACE)
def show_next_unread(self, *args): def show_next_unread(self, *args):
'''Show the window(s) with next waiting messages in tabbed/group chats. ''' '''Show the window(s) with next waiting messages in tabbed/group chats. '''
if gajim.events.get_nb_events(): if gajim.events.get_nb_events():
gajim.interface.systray.handle_first_event() gajim.interface.systray.handle_first_event()
@dbus.service.method(INTERFACE)
def contact_info(self, *args): def contact_info(self, *args):
'''get vcard info for a contact. Return cached value of the vcard. '''get vcard info for a contact. Return cached value of the vcard.
''' '''
@ -375,6 +316,7 @@ class SignalObject(DbusPrototype):
# return empty dict # return empty dict
return DBUS_DICT_SV() return DBUS_DICT_SV()
@dbus.service.method(INTERFACE)
def list_accounts(self, *args): def list_accounts(self, *args):
'''list register accounts''' '''list register accounts'''
result = gajim.contacts.get_accounts() result = gajim.contacts.get_accounts()
@ -385,6 +327,7 @@ class SignalObject(DbusPrototype):
return result_array return result_array
return None return None
@dbus.service.method(INTERFACE)
def account_info(self, *args): def account_info(self, *args):
'''show info on account: resource, jid, nick, prio, message''' '''show info on account: resource, jid, nick, prio, message'''
[for_account] = self._get_real_arguments(args, 1) [for_account] = self._get_real_arguments(args, 1)
@ -394,7 +337,7 @@ class SignalObject(DbusPrototype):
account = gajim.connections[for_account] account = gajim.connections[for_account]
result = DBUS_DICT_SS() result = DBUS_DICT_SS()
index = account.connected index = account.connected
result['status'] = DBUS_STRING(STATUS_LIST[index]) result['status'] = DBUS_STRING(gajim.SHOW_LIST[index])
result['name'] = DBUS_STRING(account.name) result['name'] = DBUS_STRING(account.name)
result['jid'] = DBUS_STRING(gajim.get_jid_from_account(account.name)) result['jid'] = DBUS_STRING(gajim.get_jid_from_account(account.name))
result['message'] = DBUS_STRING(account.status) result['message'] = DBUS_STRING(account.status)
@ -404,6 +347,7 @@ class SignalObject(DbusPrototype):
account.name, 'resource'))) account.name, 'resource')))
return result return result
@dbus.service.method(INTERFACE)
def list_contacts(self, *args): def list_contacts(self, *args):
'''list all contacts in the roster. If the first argument is specified, '''list all contacts in the roster. If the first argument is specified,
then return the contacts for the specified account''' then return the contacts for the specified account'''
@ -428,6 +372,7 @@ class SignalObject(DbusPrototype):
return None return None
return result return result
@dbus.service.method(INTERFACE)
def toggle_roster_appearance(self, *args): def toggle_roster_appearance(self, *args):
''' shows/hides the roster window ''' ''' shows/hides the roster window '''
win = gajim.interface.roster.window win = gajim.interface.roster.window
@ -441,6 +386,7 @@ class SignalObject(DbusPrototype):
else: else:
win.window.focus(long(time())) win.window.focus(long(time()))
@dbus.service.method(INTERFACE)
def prefs_list(self, *args): def prefs_list(self, *args):
prefs_dict = DBUS_DICT_SS() prefs_dict = DBUS_DICT_SS()
def get_prefs(data, name, path, value): def get_prefs(data, name, path, value):
@ -455,6 +401,7 @@ class SignalObject(DbusPrototype):
gajim.config.foreach(get_prefs) gajim.config.foreach(get_prefs)
return prefs_dict return prefs_dict
@dbus.service.method(INTERFACE)
def prefs_store(self, *args): def prefs_store(self, *args):
try: try:
gajim.interface.save_config() gajim.interface.save_config()
@ -462,6 +409,7 @@ class SignalObject(DbusPrototype):
return False return False
return True return True
@dbus.service.method(INTERFACE)
def prefs_del(self, *args): def prefs_del(self, *args):
[key] = self._get_real_arguments(args, 1) [key] = self._get_real_arguments(args, 1)
if not key: if not key:
@ -475,6 +423,7 @@ class SignalObject(DbusPrototype):
gajim.config.del_per(key_path[0], key_path[1], key_path[2]) gajim.config.del_per(key_path[0], key_path[1], key_path[2])
return True return True
@dbus.service.method(INTERFACE)
def prefs_put(self, *args): def prefs_put(self, *args):
[key] = self._get_real_arguments(args, 1) [key] = self._get_real_arguments(args, 1)
if not key: if not key:
@ -488,6 +437,7 @@ class SignalObject(DbusPrototype):
gajim.config.set_per(key_path[0], key_path[1], subname, value) gajim.config.set_per(key_path[0], key_path[1], subname, value)
return True return True
@dbus.service.method(INTERFACE)
def add_contact(self, *args): def add_contact(self, *args):
[jid, account] = self._get_real_arguments(args, 2) [jid, account] = self._get_real_arguments(args, 2)
if account: if account:
@ -503,6 +453,7 @@ class SignalObject(DbusPrototype):
AddNewContactWindow(account = None, jid = jid) AddNewContactWindow(account = None, jid = jid)
return True return True
@dbus.service.method(INTERFACE)
def remove_contact(self, *args): def remove_contact(self, *args):
[jid, account] = self._get_real_arguments(args, 2) [jid, account] = self._get_real_arguments(args, 2)
jid = self._get_real_jid(jid, account) jid = self._get_real_jid(jid, account)
@ -597,9 +548,11 @@ class SignalObject(DbusPrototype):
contact_dict['resources'] = DBUS_VARIANT(contact_dict['resources']) contact_dict['resources'] = DBUS_VARIANT(contact_dict['resources'])
return contact_dict return contact_dict
@dbus.service.method(INTERFACE)
def get_unread_msgs_number(self, *args): def get_unread_msgs_number(self, *args):
return str(gajim.events.get_nb_events) return str(gajim.events.get_nb_events)
@dbus.service.method(INTERFACE)
def start_chat(self, *args): def start_chat(self, *args):
[account] = self._get_real_arguments(args, 1) [account] = self._get_real_arguments(args, 1)
if not account: if not account:
@ -608,6 +561,7 @@ class SignalObject(DbusPrototype):
NewChatDialog(account) NewChatDialog(account)
return True return True
@dbus.service.method(INTERFACE)
def send_xml(self, *args): def send_xml(self, *args):
xml, account = self._get_real_arguments(args, 2) xml, account = self._get_real_arguments(args, 2)
if account: if account:
@ -615,36 +569,3 @@ class SignalObject(DbusPrototype):
else: else:
for acc in gajim.contacts.get_accounts(): for acc in gajim.contacts.get_accounts():
gajim.connections[acc].send_stanza(xml) gajim.connections[acc].send_stanza(xml)
if dbus_support.version[1] >= 30 and dbus_support.version[1] <= 40:
method = dbus.method
signal = dbus.signal
elif dbus_support.version[1] >= 41:
method = dbus.service.method
signal = dbus.service.signal
# prevent using decorators, because they are not supported
# on python < 2.4
# FIXME: use decorators when python2.3 (and dbus 0.23) is OOOOOOLD
toggle_roster_appearance = method(INTERFACE)(toggle_roster_appearance)
list_contacts = method(INTERFACE)(list_contacts)
list_accounts = method(INTERFACE)(list_accounts)
show_next_unread = method(INTERFACE)(show_next_unread)
change_status = method(INTERFACE)(change_status)
open_chat = method(INTERFACE)(open_chat)
contact_info = method(INTERFACE)(contact_info)
send_message = method(INTERFACE)(send_chat_message)
send_single_message = method(INTERFACE)(send_single_message)
send_file = method(INTERFACE)(send_file)
prefs_list = method(INTERFACE)(prefs_list)
prefs_put = method(INTERFACE)(prefs_put)
prefs_del = method(INTERFACE)(prefs_del)
prefs_store = method(INTERFACE)(prefs_store)
remove_contact = method(INTERFACE)(remove_contact)
add_contact = method(INTERFACE)(add_contact)
get_status = method(INTERFACE)(get_status)
get_status_message = method(INTERFACE)(get_status_message)
account_info = method(INTERFACE)(account_info)
get_unread_msgs_number = method(INTERFACE)(get_unread_msgs_number)
start_chat = method(INTERFACE)(start_chat)
send_xml = method(INTERFACE)(send_xml)

View file

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
## roster_window.py ## roster_window.py
## ##
## Copyright (C) 2003-2006 Yann Le Boulanger <asterix@lagaule.org> ## Copyright (C) 2003-2006 Yann Le Boulanger <asterix@lagaule.org>
@ -39,6 +40,10 @@ from chat_control import ChatControl
from groupchat_control import GroupchatControl from groupchat_control import GroupchatControl
from groupchat_control import PrivateChatControl from groupchat_control import PrivateChatControl
import dbus_support
if dbus_support.supported:
from music_track_listener import MusicTrackListener
#(icon, name, type, jid, account, editable, second pixbuf) #(icon, name, type, jid, account, editable, second pixbuf)
( (
C_IMG, # image to show state (online, new message etc) C_IMG, # image to show state (online, new message etc)
@ -50,9 +55,6 @@ C_EDITABLE, # cellrenderer text that holds name editable or not?
C_SECPIXBUF, # secondary_pixbuf (holds avatar or padlock) C_SECPIXBUF, # secondary_pixbuf (holds avatar or padlock)
) = range(7) ) = range(7)
DEFAULT_ICONSET = 'dcraven'
class RosterWindow: class RosterWindow:
'''Class for main window of gtkgui interface''' '''Class for main window of gtkgui interface'''
@ -624,9 +626,6 @@ class RosterWindow:
self.join_gc_room(account, bookmark['jid'], bookmark['nick'], self.join_gc_room(account, bookmark['jid'], bookmark['nick'],
bookmark['password']) bookmark['password'])
def on_bm_header_changed_state(self, widget, event):
widget.set_state(gtk.STATE_NORMAL) #do not allow selected_state
def on_send_server_message_menuitem_activate(self, widget, account): def on_send_server_message_menuitem_activate(self, widget, account):
server = gajim.config.get_per('accounts', account, 'hostname') server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/online' server += '/announce/online'
@ -717,6 +716,11 @@ class RosterWindow:
return return
new_chat_menuitem = self.xml.get_widget('new_chat_menuitem') new_chat_menuitem = self.xml.get_widget('new_chat_menuitem')
join_gc_menuitem = self.xml.get_widget('join_gc_menuitem') join_gc_menuitem = self.xml.get_widget('join_gc_menuitem')
iconset = gajim.config.get('iconset')
path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
state_images = self.load_iconset(path)
if state_images.has_key('muc_active'):
join_gc_menuitem.set_image(state_images['muc_active'])
add_new_contact_menuitem = self.xml.get_widget('add_new_contact_menuitem') add_new_contact_menuitem = self.xml.get_widget('add_new_contact_menuitem')
service_disco_menuitem = self.xml.get_widget('service_disco_menuitem') service_disco_menuitem = self.xml.get_widget('service_disco_menuitem')
advanced_menuitem = self.xml.get_widget('advanced_menuitem') advanced_menuitem = self.xml.get_widget('advanced_menuitem')
@ -787,7 +791,7 @@ class RosterWindow:
label.set_use_underline(False) label.set_use_underline(False)
gc_item = gtk.MenuItem() gc_item = gtk.MenuItem()
gc_item.add(label) gc_item.add(label)
gc_item.connect('state-changed', self.on_bm_header_changed_state) gc_item.connect('state-changed', gtkgui_helpers.on_bm_header_changed_state)
gc_sub_menu.append(gc_item) gc_sub_menu.append(gc_item)
self.add_bookmarks_list(gc_sub_menu, account) self.add_bookmarks_list(gc_sub_menu, account)
@ -1084,8 +1088,12 @@ class RosterWindow:
win.redraw_tab(ctrl) win.redraw_tab(ctrl)
name = contact.get_shown_name() name = contact.get_shown_name()
if contact.resource != '':
# if multiple resources (or second one disconnecting)
if (len(contact_instances) > 1 or (len(contact_instances) == 1 and \
show in ('offline', 'error'))) and contact.resource != '':
name += '/' + contact.resource name += '/' + contact.resource
uf_show = helpers.get_uf_show(show) uf_show = helpers.get_uf_show(show)
if status: if status:
ctrl.print_conversation(_('%s is now %s (%s)') % (name, uf_show, ctrl.print_conversation(_('%s is now %s (%s)') % (name, uf_show,
@ -1204,7 +1212,7 @@ class RosterWindow:
gajim.connections[account].request_register_agent_info(contact.jid) gajim.connections[account].request_register_agent_info(contact.jid)
def on_remove_agent(self, widget, list_): def on_remove_agent(self, widget, list_):
'''When an agent is requested to log in or off. list_ is a list of '''When an agent is requested to be removed. list_ is a list of
(contact, account) tuple''' (contact, account) tuple'''
for (contact, account) in list_: for (contact, account) in list_:
if gajim.config.get_per('accounts', account, 'hostname') == \ if gajim.config.get_per('accounts', account, 'hostname') == \
@ -1226,6 +1234,17 @@ class RosterWindow:
gajim.contacts.remove_jid(account, contact.jid) gajim.contacts.remove_jid(account, contact.jid)
gajim.contacts.remove_contact(account, contact) gajim.contacts.remove_contact(account, contact)
# Check if there are unread events from some contacts
has_unread_events = False
for (contact, account) in list_:
for jid in gajim.events.get_events(account):
if jid.endswith(contact.jid):
has_unread_events = True
break
if has_unread_events:
dialogs.ErrorDialog(_('You have unread messages'),
_('You must read them before removing this transport.'))
return
if len(list_) == 1: if len(list_) == 1:
pritext = _('Transport "%s" will be removed') % contact.jid pritext = _('Transport "%s" will be removed') % contact.jid
sectext = _('You will no longer be able to send and receive messages to contacts from this transport.') sectext = _('You will no longer be able to send and receive messages to contacts from this transport.')
@ -1332,7 +1351,7 @@ class RosterWindow:
'''Make contact's popup menu''' '''Make contact's popup menu'''
model = self.tree.get_model() model = self.tree.get_model()
jid = model[iter][C_JID].decode('utf-8') jid = model[iter][C_JID].decode('utf-8')
path = model.get_path(iter) tree_path = model.get_path(iter)
account = model[iter][C_ACCOUNT].decode('utf-8') account = model[iter][C_ACCOUNT].decode('utf-8')
our_jid = jid == gajim.get_jid_from_account(account) our_jid = jid == gajim.get_jid_from_account(account)
contact = gajim.contacts.get_contact_with_highest_priority(account, jid) contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
@ -1368,6 +1387,12 @@ class RosterWindow:
img.set_from_file(path_to_kbd_input_img) img.set_from_file(path_to_kbd_input_img)
rename_menuitem.set_image(img) rename_menuitem.set_image(img)
iconset = gajim.config.get('iconset')
path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
state_images = self.load_iconset(path)
if state_images.has_key('muc_active'):
invite_menuitem.set_image(state_images['muc_active'])
above_subscription_separator = xml.get_widget( above_subscription_separator = xml.get_widget(
'above_subscription_separator') 'above_subscription_separator')
subscription_menuitem = xml.get_widget('subscription_menuitem') subscription_menuitem = xml.get_widget('subscription_menuitem')
@ -1387,8 +1412,6 @@ class RosterWindow:
start_chat_menuitem.set_submenu(sub_menu) start_chat_menuitem.set_submenu(sub_menu)
iconset = gajim.config.get('iconset') iconset = gajim.config.get('iconset')
if not iconset:
iconset = DEFAULT_ICONSET
path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16') path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
for c in contacts: for c in contacts:
# icon MUST be different instance for every item # icon MUST be different instance for every item
@ -1403,7 +1426,7 @@ class RosterWindow:
else: # one resource else: # one resource
start_chat_menuitem.connect('activate', start_chat_menuitem.connect('activate',
self.on_roster_treeview_row_activated, path) self.on_roster_treeview_row_activated, tree_path)
if contact.resource: if contact.resource:
send_file_menuitem.connect('activate', send_file_menuitem.connect('activate',
@ -1444,7 +1467,7 @@ class RosterWindow:
menuitem.connect('activate', self.on_invite_to_room, menuitem.connect('activate', self.on_invite_to_room,
[(contact, account)], room_jid, acct) [(contact, account)], room_jid, acct)
submenu.append(menuitem) submenu.append(menuitem)
rename_menuitem.connect('activate', self.on_rename, iter, path) rename_menuitem.connect('activate', self.on_rename, iter, tree_path)
remove_from_roster_menuitem.connect('activate', self.on_req_usub, remove_from_roster_menuitem.connect('activate', self.on_req_usub,
[(contact, account)]) [(contact, account)])
information_menuitem.connect('activate', self.on_info, contact, information_menuitem.connect('activate', self.on_info, contact,
@ -1774,8 +1797,6 @@ class RosterWindow:
# we have to create our own set of icons for the menu # we have to create our own set of icons for the menu
# using self.jabber_status_images is poopoo # using self.jabber_status_images is poopoo
iconset = gajim.config.get('iconset') iconset = gajim.config.get('iconset')
if not iconset:
iconset = DEFAULT_ICONSET
path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16') path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
state_images = self.load_iconset(path) state_images = self.load_iconset(path)
@ -1908,8 +1929,6 @@ class RosterWindow:
else: else:
menu = gtk.Menu() menu = gtk.Menu()
iconset = gajim.config.get('iconset') iconset = gajim.config.get('iconset')
if not iconset:
iconset = DEFAULT_ICONSET
path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16') path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
accounts = [] # Put accounts in a list to sort them accounts = [] # Put accounts in a list to sort them
for account in gajim.connections: for account in gajim.connections:
@ -2419,6 +2438,41 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
self.send_status(acct, status, message) self.send_status(acct, status, message)
self.update_status_combobox() self.update_status_combobox()
## enable setting status msg from currently playing music track
def enable_syncing_status_msg_from_current_music_track(self, enabled):
'''if enabled is True, we listen to events from music players about
currently played music track, and we update our
status message accordinly'''
if not dbus_support.supported:
# do nothing if user doesn't have D-Bus bindings
return
if enabled:
if self._music_track_changed_signal is None:
listener = MusicTrackListener.get()
self._music_track_changed_signal = listener.connect(
'music-track-changed', self._music_track_changed)
track = listener.get_playing_track()
self._music_track_changed(listener, track)
else:
if self._music_track_changed_signal is not None:
listener = MusicTrackListener.get()
listener.disconnect(self._music_track_changed_signal)
self._music_track_changed_signal = None
self._music_track_changed(None, None)
def _music_track_changed(self, unused_listener, music_track_info):
accounts = gajim.connections.keys()
if music_track_info is None:
status_message = ''
else:
status_message = _('"%(title)s" by %(artist)s') % \
{'title': music_track_info.title,
'artist': music_track_info.artist }
for acct in accounts:
current_show = gajim.SHOW_LIST[gajim.connections[acct].connected]
self.send_status(acct, current_show, status_message)
def update_status_combobox(self): def update_status_combobox(self):
# table to change index in connection.connected to index in combobox # table to change index in connection.connected to index in combobox
table = {'offline':9, 'connecting':9, 'online':0, 'chat':1, 'away':2, table = {'offline':9, 'connecting':9, 'online':0, 'chat':1, 'away':2,
@ -2599,12 +2653,12 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
# We save it in a queue # We save it in a queue
type_ = 'chat' type_ = 'chat'
event_type = 'message_received'
if msg_type == 'normal': if msg_type == 'normal':
type_ = 'normal' type_ = 'normal'
show_in_roster = notify.get_show_in_roster('message_received', account, event_type = 'single_message_received'
contact) show_in_roster = notify.get_show_in_roster(event_type, account, contact)
show_in_systray = notify.get_show_in_systray('message_received', account, show_in_systray = notify.get_show_in_systray(event_type, account, contact)
contact)
event = gajim.events.create_event(type_, (msg, subject, msg_type, tim, event = gajim.events.create_event(type_, (msg, subject, msg_type, tim,
encrypted, resource, msg_id), show_in_roster = show_in_roster, encrypted, resource, msg_id), show_in_roster = show_in_roster,
show_in_systray = show_in_systray) show_in_systray = show_in_systray)
@ -3134,8 +3188,13 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
def make_jabber_state_images(self): def make_jabber_state_images(self):
'''initialise jabber_state_images dict''' '''initialise jabber_state_images dict'''
iconset = gajim.config.get('iconset') iconset = gajim.config.get('iconset')
if not iconset: if iconset:
iconset = 'dcraven' path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
if not os.path.exists(path):
iconset = gajim.config.DEFAULT_ICONSET
else:
iconset = gajim.config.DEFAULT_ICONSET
path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '32x32') path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '32x32')
self.jabber_state_images['32'] = self.load_iconset(path) self.jabber_state_images['32'] = self.load_iconset(path)
@ -3174,6 +3233,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
model[iter][1] = self.jabber_state_images['16'][model[iter][2]] model[iter][1] = self.jabber_state_images['16'][model[iter][2]]
iter = model.iter_next(iter) iter = model.iter_next(iter)
# Update the systray # Update the systray
if gajim.interface.systray_enabled:
gajim.interface.systray.set_img() gajim.interface.systray.set_img()
for win in gajim.interface.msg_win_mgr.windows(): for win in gajim.interface.msg_win_mgr.windows():
@ -3722,6 +3782,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
def __init__(self): def __init__(self):
self.xml = gtkgui_helpers.get_glade('roster_window.glade') self.xml = gtkgui_helpers.get_glade('roster_window.glade')
self.window = self.xml.get_widget('roster_window') self.window = self.xml.get_widget('roster_window')
self._music_track_changed_signal = None
gajim.interface.msg_win_mgr = MessageWindowMgr() gajim.interface.msg_win_mgr = MessageWindowMgr()
self.advanced_menus = [] # We keep them to destroy them self.advanced_menus = [] # We keep them to destroy them
if gajim.config.get('roster_window_skip_taskbar'): if gajim.config.get('roster_window_skip_taskbar'):
@ -3898,6 +3959,13 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
self.tooltip = tooltips.RosterTooltip() self.tooltip = tooltips.RosterTooltip()
self.draw_roster() self.draw_roster()
## Music Track notifications
## FIXME: we use a timeout because changing status of
## accounts has no effect until they are connected.
gobject.timeout_add(1000,
self.enable_syncing_status_msg_from_current_music_track,
gajim.config.get('set_status_msg_from_current_music_track'))
if gajim.config.get('show_roster_on_startup'): if gajim.config.get('show_roster_on_startup'):
self.window.show_all() self.window.show_all()
else: else:

View file

@ -124,11 +124,12 @@ class Systray:
# We need our own set of status icons, let's make 'em! # We need our own set of status icons, let's make 'em!
iconset = gajim.config.get('iconset') iconset = gajim.config.get('iconset')
if not iconset:
iconset = 'dcraven'
path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16') path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
state_images = gajim.interface.roster.load_iconset(path) state_images = gajim.interface.roster.load_iconset(path)
if state_images.has_key('muc_active'):
join_gc_menuitem.set_image(state_images['muc_active'])
for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'):
uf_show = helpers.get_uf_show(show, use_mnemonic = True) uf_show = helpers.get_uf_show(show, use_mnemonic = True)
item = gtk.ImageMenuItem(uf_show) item = gtk.ImageMenuItem(uf_show)
@ -194,6 +195,7 @@ class Systray:
label.set_use_underline(False) label.set_use_underline(False)
gc_item = gtk.MenuItem() gc_item = gtk.MenuItem()
gc_item.add(label) gc_item.add(label)
gc_item.connect('state-changed', gtkgui_helpers.on_bm_header_changed_state)
gc_sub_menu.append(gc_item) 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)
@ -250,11 +252,11 @@ class Systray:
if len(gajim.events.get_systray_events()) == 0: if len(gajim.events.get_systray_events()) == 0:
# no pending events, so toggle visible/hidden for roster window # no pending events, so toggle visible/hidden for roster window
if win.get_property('visible'): # visible in ANY virtual desktop? if win.get_property('visible'): # visible in ANY virtual desktop?
win.hide() # we hide it from VD that was visible in
# but we could be in another VD right now. eg vd2 # we could be in another VD right now. eg vd2
# and we want not only to hide it in vd1 but also show it in vd2 # and we want to show it in vd2
gtkgui_helpers.possibly_move_window_in_current_desktop(win) if not gtkgui_helpers.possibly_move_window_in_current_desktop(win):
win.hide() # else we hide it from VD that was visible in
else: else:
win.present() win.present()
else: else:

View file

@ -61,6 +61,7 @@ class VcardWindow:
# the contact variable is the jid if vcard is true # the contact variable is the jid if vcard is true
self.xml = gtkgui_helpers.get_glade('vcard_information_window.glade') self.xml = gtkgui_helpers.get_glade('vcard_information_window.glade')
self.window = self.xml.get_widget('vcard_information_window') self.window = self.xml.get_widget('vcard_information_window')
self.progressbar = self.xml.get_widget('progressbar')
self.contact = contact self.contact = contact
self.account = account self.account = account
@ -68,13 +69,23 @@ class VcardWindow:
self.avatar_mime_type = None self.avatar_mime_type = None
self.avatar_encoded = None self.avatar_encoded = None
self.vcard_arrived = False
self.os_info_arrived = False
self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar)
self.fill_jabber_page() self.fill_jabber_page()
self.xml.signal_autoconnect(self) self.xml.signal_autoconnect(self)
self.window.show_all() self.window.show_all()
def update_progressbar(self):
self.progressbar.pulse()
return True # loop forever
def on_vcard_information_window_destroy(self, widget): def on_vcard_information_window_destroy(self, widget):
if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id)
del gajim.interface.instances[self.account]['infos'][self.contact.jid] del gajim.interface.instances[self.account]['infos'][self.contact.jid]
def on_vcard_information_window_key_press_event(self, widget, event): def on_vcard_information_window_key_press_event(self, widget, event):
@ -113,6 +124,14 @@ class VcardWindow:
def set_value(self, entry_name, value): def set_value(self, entry_name, value):
try: try:
if value and entry_name == 'URL_label':
if gtk.pygtk_version >= (2, 10, 0) and gtk.gtk_version >= (2, 10, 0):
widget = gtk.LinkButton(value, value)
else:
widget = gtk.Label(value)
table = self.xml.get_widget('personal_info_table')
table.attach(widget, 1, 4, 3, 4, yoptions = 0)
else:
self.xml.get_widget(entry_name).set_text(value) self.xml.get_widget(entry_name).set_text(value)
except AttributeError: except AttributeError:
pass pass
@ -144,8 +163,17 @@ class VcardWindow:
if i == 'DESC': if i == 'DESC':
self.xml.get_widget('DESC_textview').get_buffer().set_text( self.xml.get_widget('DESC_textview').get_buffer().set_text(
vcard[i], 0) vcard[i], 0)
else: elif i != 'jid': # Do not override jid_label
self.set_value(i + '_label', vcard[i]) self.set_value(i + '_label', vcard[i])
self.vcard_arrived = True
self.test_remove_progressbar()
def test_remove_progressbar(self):
if self.update_progressbar_timeout_id is not None and \
self.vcard_arrived and self.os_info_arrived:
gobject.source_remove(self.update_progressbar_timeout_id)
self.progressbar.hide()
self.update_progressbar_timeout_id = None
def set_last_status_time(self): def set_last_status_time(self):
self.fill_status_label() self.fill_status_label()
@ -174,6 +202,8 @@ class VcardWindow:
os = Q_('?OS:Unknown') os = Q_('?OS:Unknown')
self.xml.get_widget('client_name_version_label').set_text(client) self.xml.get_widget('client_name_version_label').set_text(client)
self.xml.get_widget('os_label').set_text(os) self.xml.get_widget('os_label').set_text(os)
self.os_info_arrived = True
self.test_remove_progressbar()
def fill_status_label(self): def fill_status_label(self):
if self.xml.get_widget('information_notebook').get_n_pages() < 4: if self.xml.get_widget('information_notebook').get_n_pages() < 4:
@ -251,8 +281,10 @@ class VcardWindow:
gajim.connections[self.account].request_last_status_time(self.contact.jid, gajim.connections[self.account].request_last_status_time(self.contact.jid,
self.contact.resource) self.contact.resource)
# Request os info in contact is connected # do not wait for os_info if contact is not connected
if self.contact.show not in ('offline', 'error'): if self.contact.show in ('offline', 'error'):
self.os_info_arrived = True
else: # Request os info if contact is connected
gobject.idle_add(gajim.connections[self.account].request_os_info, gobject.idle_add(gajim.connections[self.account].request_os_info,
self.contact.jid, self.contact.resource) self.contact.jid, self.contact.resource)
self.os_info = {0: {'resource': self.contact.resource, 'client': '', self.os_info = {0: {'resource': self.contact.resource, 'client': '',
@ -283,3 +315,6 @@ class VcardWindow:
self.fill_status_label() 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.is_fake)
def on_close_button_clicked(self, widget):
self.window.destroy()