Merging changes from trunk (6496:6561)

This commit is contained in:
Tomasz Melcer 2006-07-17 19:30:53 +00:00
parent 5740d226e6
commit 585ab90e92
50 changed files with 69428 additions and 52403 deletions

1
THANKS
View file

@ -19,6 +19,7 @@ Geobert Quach
Guillaume Morin Guillaume Morin
Gustavo J. A. M. Carneiro Gustavo J. A. M. Carneiro
Ivo Anjo Ivo Anjo
Julien Pivotto
Juraj Michalek Juraj Michalek
Luis Peralta Luis Peralta
Michele Campeotto Michele Campeotto

View file

@ -30,6 +30,13 @@
</widget> </widget>
</child> </child>
<child>
<widget class="GtkMenuItem" id="privacy_lists_menuitem">
<property name="label" translatable="yes">_Privacy Lists</property>
<property name="use_underline">True</property>
</widget>
</child>
<child> <child>
<widget class="GtkSeparatorMenuItem" id="separator8"> <widget class="GtkSeparatorMenuItem" id="separator8">
</widget> </widget>

File diff suppressed because it is too large Load diff

View file

@ -3080,6 +3080,106 @@ Custom</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkFrame" id="frame_gmail">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<child>
<widget class="GtkAlignment" id="alignment_gmail">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkVBox" id="vbox_gmail">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<widget class="GtkCheckButton" id="notify_gmail_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Notify on new _GMail email</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_notify_gmail_checkbutton_toggled" last_modification_time="Wed, 06 Apr 2005 14:43:56 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="notify_gmail_extra_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Display _extra email details</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_notify_gmail_extra_checkbutton_toggled" last_modification_time="Wed, 06 Apr 2005 14:43:56 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="gmail_options_label">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;GMail Options&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="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child> <child>
<widget class="GtkFrame" id="frame27"> <widget class="GtkFrame" id="frame27">
<property name="visible">True</property> <property name="visible">True</property>
@ -3146,24 +3246,6 @@ Custom</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkCheckButton" id="notify_gmail_checkbutton">
<property name="can_focus">True</property>
<property name="label" translatable="yes">Notify on new _Gmail e-mail</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_notify_gmail_checkbutton_toggled" last_modification_time="Wed, 06 Apr 2005 14:43:56 GMT"/>
</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

@ -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

@ -40,6 +40,8 @@ gajim.pot: ../src/*py ../src/common/*py \
../data/glade/passphrase_dialog.glade.h \ ../data/glade/passphrase_dialog.glade.h \
../data/glade/popup_notification_window.glade.h \ ../data/glade/popup_notification_window.glade.h \
../data/glade/preferences_window.glade.h \ ../data/glade/preferences_window.glade.h \
../data/glade/privacy_list_edit_window.glade.h \
../data/glade/privacy_lists_first_window.glade.h \
../data/glade/progress_dialog.glade.h \ ../data/glade/progress_dialog.glade.h \
../data/glade/remove_account_window.glade.h \ ../data/glade/remove_account_window.glade.h \
../data/glade/roster_contact_context_menu.glade.h \ ../data/glade/roster_contact_context_menu.glade.h \

View file

@ -35,6 +35,8 @@ data/glade/message_window.glade
data/glade/passphrase_dialog.glade data/glade/passphrase_dialog.glade
data/glade/popup_notification_window.glade data/glade/popup_notification_window.glade
data/glade/preferences_window.glade data/glade/preferences_window.glade
data/glade/privacy_list_edit_window.glade
data/glade/privacy_lists_first_window.glade
data/glade/progress_dialog.glade data/glade/progress_dialog.glade
data/glade/remove_account_window.glade data/glade/remove_account_window.glade
data/glade/roster_contact_context_menu.glade data/glade/roster_contact_context_menu.glade

5450
po/bg.po

File diff suppressed because it is too large Load diff

5965
po/br.po

File diff suppressed because it is too large Load diff

5557
po/cs.po

File diff suppressed because it is too large Load diff

5555
po/de.po

File diff suppressed because it is too large Load diff

5566
po/el.po

File diff suppressed because it is too large Load diff

5414
po/eo.po

File diff suppressed because it is too large Load diff

5571
po/es.po

File diff suppressed because it is too large Load diff

6088
po/eu.po

File diff suppressed because it is too large Load diff

6280
po/fr.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

5548
po/it.po

File diff suppressed because it is too large Load diff

6023
po/nb.po

File diff suppressed because it is too large Load diff

5565
po/nl.po

File diff suppressed because it is too large Load diff

6023
po/no.po

File diff suppressed because it is too large Load diff

5626
po/pl.po

File diff suppressed because it is too large Load diff

5577
po/pt.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

5556
po/ru.po

File diff suppressed because it is too large Load diff

6499
po/sk.po

File diff suppressed because it is too large Load diff

6093
po/sv.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -514,12 +514,10 @@ class ChatControlBase(MessageControl):
def on_actions_button_clicked(self, widget): def on_actions_button_clicked(self, widget):
'''popup action menu''' '''popup action menu'''
#FIXME: BUG http://bugs.gnome.org/show_bug.cgi?id=316786
self.button_clicked = widget
menu = self.prepare_context_menu() menu = self.prepare_context_menu()
menu.show_all() menu.show_all()
gtkgui_helpers.popup_emoticons_under_button(menu, widget, self.parent_win) gtkgui_helpers.popup_emoticons_under_button(menu, widget,
self.parent_win)
def update_font(self): def update_font(self):
font = pango.FontDescription(gajim.config.get('conversation_font')) font = pango.FontDescription(gajim.config.get('conversation_font'))
@ -636,7 +634,10 @@ class ChatControlBase(MessageControl):
def on_conversation_vadjustment_value_changed(self, widget): def on_conversation_vadjustment_value_changed(self, widget):
if not self.nb_unread: if not self.nb_unread:
return return
jid = self.contact.jid if self.resource:
jid = self.contact.get_full_jid()
else:
jid = self.contact.jid
if self.conv_textview.at_the_end() and \ if self.conv_textview.at_the_end() and \
self.parent_win.get_active_control() == self and \ self.parent_win.get_active_control() == self and \
self.parent_win.window.is_active(): self.parent_win.window.is_active():
@ -1574,6 +1575,9 @@ class ChatControl(ChatControlBase):
def show_bigger_avatar(self, small_avatar): def show_bigger_avatar(self, small_avatar):
'''resizes the avatar, if needed, so it has at max half the screen size '''resizes the avatar, if needed, so it has at max half the screen size
and shows it''' and shows it'''
if not small_avatar.window:
# Tab has been closed since we hovered the avatar
return
is_fake = False is_fake = False
if self.type_id == message_control.TYPE_PM: if self.type_id == message_control.TYPE_PM:
is_fake = True is_fake = True

View file

@ -125,6 +125,7 @@ class Config:
'after_nickname': [ opt_str, ':' ], 'after_nickname': [ opt_str, ':' ],
'send_os_info': [ opt_bool, True ], 'send_os_info': [ opt_bool, True ],
'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 ],
'usegpg': [ opt_bool, False, '', True ], 'usegpg': [ opt_bool, False, '', True ],
'use_gpg_agent': [ opt_bool, False ], 'use_gpg_agent': [ opt_bool, False ],
'change_roster_title': [ opt_bool, True, _('Add * and [n] in roster title?')], 'change_roster_title': [ opt_bool, True, _('Add * and [n] in roster title?')],
@ -200,6 +201,7 @@ class Config:
'hide_groupchat_occupants_list': [opt_bool, False, _('Hides the room occupants list in groupchat window')], 'hide_groupchat_occupants_list': [opt_bool, False, _('Hides the room occupants list in groupchat window')],
'chat_merge_consecutive_nickname': [opt_bool, False, _('Merge consecutive nickname in chat window')], 'chat_merge_consecutive_nickname': [opt_bool, False, _('Merge consecutive nickname in chat window')],
'chat_merge_consecutive_nickname_indent': [opt_str, ' ', _('Indentation when using merge consecutive nickame')], 'chat_merge_consecutive_nickname_indent': [opt_str, ' ', _('Indentation when using merge consecutive nickame')],
'gc_nicknames_colors': [ opt_str, '#a34526:#c000ff:#0012ff:#388a99:#38995d:#519938:#ff8a00:#94452d:#244b5a:#32645a', _('List of colors that will be used to color nicknames in groupchats'), True ],
} }
__options_per_key = { __options_per_key = {
@ -289,6 +291,22 @@ class Config:
'contacts': ({ 'contacts': ({
'gpg_enabled': [ opt_bool, True ], 'gpg_enabled': [ opt_bool, True ],
}, {}), }, {}),
'notifications': ({
'event': [opt_str, ''],
'recipient_type': [opt_str, 'all'],
'recipients': [opt_str, ''],
'status': [opt_str, 'all', _('all or space separated status')],
'tab_opened': [opt_str, 'both', _("'yes', 'no', or 'both'")],
'sound': [opt_str, '', _("'yes', 'no' or ''")],
'sound_file': [opt_str, ''],
'popup': [opt_str, '', _("'yes', 'no' or ''")],
'auto_open': [opt_str, '', _("'yes', 'no' or ''")],
'run_command': [opt_bool, False],
'command': [opt_str, ''],
'systray': [opt_str, '', _("'yes', 'no' or ''")],
'roster': [opt_str, '', _("'yes', 'no' or ''")],
'urgency_hint': [opt_bool, False],
}, {}),
} }
statusmsg_default = { statusmsg_default = {

View file

@ -217,6 +217,34 @@ class Connection(ConnectionHandlers):
else: else:
conf = data[1].asDict() conf = data[1].asDict()
self.dispatch('REGISTER_AGENT_INFO', (data[0], conf, is_form)) self.dispatch('REGISTER_AGENT_INFO', (data[0], conf, is_form))
elif realm == common.xmpp.NS_PRIVACY:
if event == common.xmpp.features_nb.PRIVACY_LISTS_RECEIVED:
# data is (list)
self.dispatch('PRIVACY_LISTS_RECEIVED', (data))
elif event == common.xmpp.features_nb.PRIVACY_LIST_RECEIVED:
# data is (resp)
if not data:
return
rules = []
name = data.getTag('query').getTag('list').getAttr('name')
for child in data.getTag('query').getTag('list').getChildren():
dict_item = child.getAttrs()
childs = []
if dict_item.has_key('type'):
for scnd_child in child.getChildren():
childs += [scnd_child.getName()]
rules.append({'action':dict_item['action'],
'type':dict_item['type'], 'order':dict_item['order'],
'value':dict_item['value'], 'child':childs})
else:
for scnd_child in child.getChildren():
childs.append(scnd_child.getName())
rules.append({'action':dict_item['action'],
'order':dict_item['order'], 'child':childs})
self.dispatch('PRIVACY_LIST_RECEIVED', (name, rules))
elif event == common.xmpp.features_nb.PRIVACY_LISTS_ACTIVE_DEFAULT:
# data is (dict)
self.dispatch('PRIVACY_LISTS_ACTIVE_DEFAULT', (data))
elif realm == '': elif realm == '':
if event == common.xmpp.transports.DATA_RECEIVED: if event == common.xmpp.transports.DATA_RECEIVED:
self.dispatch('STANZA_ARRIVED', unicode(data, errors = 'ignore')) self.dispatch('STANZA_ARRIVED', unicode(data, errors = 'ignore'))
@ -439,6 +467,41 @@ class Connection(ConnectionHandlers):
if kill_core and self.connected > 1: if kill_core and self.connected > 1:
self.disconnect(on_purpose = True) self.disconnect(on_purpose = True)
def get_privacy_lists(self):
if not self.connection:
return
common.xmpp.features_nb.getPrivacyLists(self.connection)
def get_active_default_lists(self):
if not self.connection:
return
common.xmpp.features_nb.getActiveAndDefaultPrivacyLists(self.connection)
def del_privacy_list(self, privacy_list):
if not self.connection:
return
common.xmpp.features_nb.delPrivacyList(self.connection, privacy_list)
def get_privacy_list(self, title):
if not self.connection:
return
common.xmpp.features_nb.getPrivacyList(self.connection, title)
def set_privacy_list(self, listname, tags):
if not self.connection:
return
common.xmpp.features_nb.setPrivacyList(self.connection, listname, tags)
def set_active_list(self, listname):
if not self.connection:
return
common.xmpp.features_nb.setActivePrivacyList(self.connection, listname, 'active')
def set_default_list(self, listname):
if not self.connection:
return
common.xmpp.features_nb.setDefaultPrivacyList(self.connection, listname)
def build_privacy_rule(self, name, action): def build_privacy_rule(self, name, action):
'''Build a Privacy rule stanza for invisibility''' '''Build a Privacy rule stanza for invisibility'''
iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '') iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '')
@ -448,6 +511,8 @@ class Connection(ConnectionHandlers):
return iq return iq
def activate_privacy_rule(self, name): def activate_privacy_rule(self, name):
if not self.connection:
return
'''activate a privacy rule''' '''activate a privacy rule'''
iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '') iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '')
iq.getTag('query').setTag('active', {'name': name}) iq.getTag('query').setTag('active', {'name': name})

View file

@ -1257,9 +1257,20 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
newmsgs = gm.getTag('mailbox').getAttr('total-matched') newmsgs = gm.getTag('mailbox').getAttr('total-matched')
if newmsgs != '0': if newmsgs != '0':
# there are new messages # there are new messages
gmail_messages_list = []
if gm.getTag('mailbox').getTag('mail-thread-info'):
gmail_messages = gm.getTag('mailbox').getTags('mail-thread-info')
for gmessage in gmail_messages:
gmail_from = gmessage.getTag('senders').getTag('sender').getAttr('address')
gmail_subject = gmessage.getTag('subject').getData()
gmail_snippet = gmessage.getTag('snippet').getData()
gmail_messages_list.append({ \
'From': gmail_from, \
'Subject': gmail_subject, \
'Snippet': gmail_snippet})
jid = gajim.get_jid_from_account(self.name) jid = gajim.get_jid_from_account(self.name)
gajim.log.debug(('You have %s new gmail e-mails on %s.') % (newmsgs, jid)) gajim.log.debug(('You have %s new gmail e-mails on %s.') % (newmsgs, jid))
self.dispatch('GMAIL_NOTIFY', (jid, newmsgs)) self.dispatch('GMAIL_NOTIFY', (jid, newmsgs, gmail_messages_list))
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
def _messageCB(self, con, msg): def _messageCB(self, con, msg):
@ -1733,7 +1744,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
# If it's a gmail account, # If it's a gmail account,
# inform the server that we want e-mail notifications # inform the server that we want e-mail notifications
if gajim.get_server_from_jid(our_jid) == 'gmail.com': if gajim.get_server_from_jid(our_jid) in gajim.gmail_domains:
gajim.log.debug(('%s is a gmail account. Setting option ' gajim.log.debug(('%s is a gmail account. Setting option '
'to get e-mail notifications on the server.') % (our_jid)) 'to get e-mail notifications on the server.') % (our_jid))
iq = common.xmpp.Iq(typ = 'set', to = our_jid) iq = common.xmpp.Iq(typ = 'set', to = our_jid)

View file

@ -324,8 +324,11 @@ class Contacts:
max_order = data_['order'] max_order = data_['order']
contact = self.get_contact_with_highest_priority(account, jid) contact = self.get_contact_with_highest_priority(account, jid)
score = (max_order - order)*10000 score = (max_order - order)*10000
if not common.gajim.jid_is_transport(jid):
score += contact.priority*10 if common.gajim.get_transport_name_from_jid(jid) is None:
score += 10
if contact.priority > 0:
score += contact.priority * 10
score += ['not in roster', 'error', 'offline', 'invisible', 'dnd', 'xa', score += ['not in roster', 'error', 'offline', 'invisible', 'dnd', 'xa',
'away', 'chat', 'online', 'requested', 'message'].index(contact.show) 'away', 'chat', 'online', 'requested', 'message'].index(contact.show)
return score return score

View file

@ -25,8 +25,8 @@ import config
from contacts import Contacts from contacts import Contacts
interface = None # The actual interface (the gtk one for the moment) interface = None # The actual interface (the gtk one for the moment)
version = '0.10'
config = config.Config() config = config.Config()
version = config.get('version')
connections = {} connections = {}
verbose = False verbose = False
@ -81,6 +81,8 @@ if LANG is None:
else: else:
LANG = LANG[:2] # en, fr, el etc.. LANG = LANG[:2] # en, fr, el etc..
gmail_domains = ['gmail.com', 'googlemail.com']
last_message_time = {} # list of time of the latest incomming message last_message_time = {} # list of time of the latest incomming message
# {acct1: {jid1: time1, jid2: time2}, } # {acct1: {jid1: time1, jid2: time2}, }
encrypted_chats = {} # list of encrypted chats {acct1: [jid1, jid2], ..} encrypted_chats = {} # list of encrypted chats {acct1: [jid1, jid2], ..}

View file

@ -418,8 +418,10 @@ def play_sound(event):
if not gajim.config.get('sounds_on'): if not gajim.config.get('sounds_on'):
return return
path_to_soundfile = gajim.config.get_per('soundevents', event, 'path') path_to_soundfile = gajim.config.get_per('soundevents', event, 'path')
player = gajim.config.get('soundplayer') play_sound_file(path_to_soundfile)
if player == 'beep':
def play_sound_file(path_to_soundfile):
if path_to_soundfile == 'beep':
print '\a' # make a speaker beep print '\a' # make a speaker beep
return return
if path_to_soundfile is None or not os.path.exists(path_to_soundfile): if path_to_soundfile is None or not os.path.exists(path_to_soundfile):
@ -431,8 +433,9 @@ def play_sound(event):
except: except:
pass pass
elif os.name == 'posix': elif os.name == 'posix':
if player == '': if gajim.config.get('soundplayer') == '':
return return
player = gajim.config.get('soundplayer')
# we add the path in "" so we have good parsing from shell # we add the path in "" so we have good parsing from shell
path_to_soundfile = path_to_soundfile.replace('"', '\\"') # escape " path_to_soundfile = path_to_soundfile.replace('"', '\\"') # escape "
command = player + ' "' + path_to_soundfile + '" &' command = player + ' "' + path_to_soundfile + '" &'

View file

@ -27,6 +27,9 @@ All these methods takes 'disp' first argument that should be already connected
from protocol import * from protocol import *
REGISTER_DATA_RECEIVED='REGISTER DATA RECEIVED' REGISTER_DATA_RECEIVED='REGISTER DATA RECEIVED'
PRIVACY_LISTS_RECEIVED='PRIVACY LISTS RECEIVED'
PRIVACY_LIST_RECEIVED='PRIVACY LIST RECEIVED'
PRIVACY_LISTS_ACTIVE_DEFAULT='PRIVACY LISTS ACTIVE DEFAULT'
### DISCO ### http://jabber.org/protocol/disco ### JEP-0030 #################### ### DISCO ### http://jabber.org/protocol/disco ### JEP-0030 ####################
### Browse ### jabber:iq:browse ### JEP-0030 ################################### ### Browse ### jabber:iq:browse ### JEP-0030 ###################################

View file

@ -14,7 +14,7 @@
# $Id: features.py,v 1.22 2005/09/30 20:13:04 mikealbon Exp $ # $Id: features.py,v 1.22 2005/09/30 20:13:04 mikealbon Exp $
from features import REGISTER_DATA_RECEIVED from features import REGISTER_DATA_RECEIVED, PRIVACY_LISTS_RECEIVED, PRIVACY_LIST_RECEIVED, PRIVACY_LISTS_ACTIVE_DEFAULT
from protocol import * from protocol import *
def _on_default_response(disp, iq, cb): def _on_default_response(disp, iq, cb):
@ -146,9 +146,9 @@ def register(disp, host, info, cb):
attributes lastErrNode, lastErr and lastErrCode. attributes lastErrNode, lastErr and lastErrCode.
""" """
iq=Iq('set', NS_REGISTER, to=host) iq=Iq('set', NS_REGISTER, to=host)
if not isinstance(info, dict): if not isinstance(info, dict):
info=info.asDict() info=info.asDict()
for i in info.keys(): for i in info.keys():
iq.setTag('query').setTagData(i,info[i]) iq.setTag('query').setTagData(i,info[i])
disp.SendAndCallForResponse(iq, cb) disp.SendAndCallForResponse(iq, cb)
@ -172,37 +172,46 @@ def changePasswordTo(disp, newpassword, host=None, cb = None):
#type=[jid|group|subscription] #type=[jid|group|subscription]
#action=[allow|deny] #action=[allow|deny]
def getPrivacyLists(disp, cb): def getPrivacyLists(disp):
""" Requests privacy lists from connected server. """ Requests privacy lists from connected server.
Returns dictionary of existing lists on success.""" Returns dictionary of existing lists on success."""
iq = Iq('get', NS_PRIVACY) iq = Iq('get', NS_PRIVACY)
def _on_response(resp): def _on_response(resp):
dict = {'lists': []} dict = {'lists': []}
try: if not isResultNode(resp):
if not isResultNode(resp): disp.Event(NS_PRIVACY, PRIVACY_LISTS_RECEIVED, (False))
cb(False) return
return for list in resp.getQueryPayload():
for list in resp.getQueryPayload(): if list.getName()=='list':
if list.getName()=='list': dict['lists'].append(list.getAttr('name'))
dict['lists'].append(list.getAttr('name')) else:
else: dict[list.getName()]=list.getAttr('name')
dict[list.getName()]=list.getAttr('name') disp.Event(NS_PRIVACY, PRIVACY_LISTS_RECEIVED, (dict))
cb(dict) disp.SendAndCallForResponse(iq, _on_response)
except:
pass
cb(False)
disp.SendAndCallForResponse(iq, _on_respons)
def getPrivacyList(disp, listname, cb): def getActiveAndDefaultPrivacyLists(disp):
iq = Iq('get', NS_PRIVACY)
def _on_response(resp):
dict = {'active': '', 'default': ''}
if not isResultNode(resp):
disp.Event(NS_PRIVACY, PRIVACY_LISTS_ACTIVE_DEFAULT, (False))
return
for list in resp.getQueryPayload():
if list.getName() == 'active':
dict['active'] = list.getAttr('name')
elif list.getName() == 'default':
dict['default'] = list.getAttr('name')
disp.Event(NS_PRIVACY, PRIVACY_LISTS_ACTIVE_DEFAULT, (dict))
disp.SendAndCallForResponse(iq, _on_response)
def getPrivacyList(disp, listname):
""" Requests specific privacy list listname. Returns list of XML nodes (rules) """ Requests specific privacy list listname. Returns list of XML nodes (rules)
taken from the server responce.""" taken from the server responce."""
def _on_response(resp): def _on_response(resp):
try: if not isResultNode(resp):
if isResultNode(resp): disp.Event(NS_PRIVACY, PRIVACY_LIST_RECEIVED, (False))
return cb(resp.getQueryPayload()[0]) return
except: disp.Event(NS_PRIVACY, PRIVACY_LIST_RECEIVED, (resp))
pass
cb(False)
iq = Iq('get', NS_PRIVACY, payload=[Node('list', {'name': listname})]) iq = Iq('get', NS_PRIVACY, payload=[Node('list', {'name': listname})])
disp.SendAndCallForResponse(iq, _on_response) disp.SendAndCallForResponse(iq, _on_response)
@ -220,14 +229,25 @@ def setDefaultPrivacyList(disp, listname=None):
""" Sets the default privacy list as 'listname'. Returns true on success.""" """ Sets the default privacy list as 'listname'. Returns true on success."""
return setActivePrivacyList(disp, listname,'default') return setActivePrivacyList(disp, listname,'default')
def setPrivacyList(disp, list, cb): def setPrivacyList(disp, listname, tags):
""" Set the ruleset. 'list' should be the simpleXML node formatted """ Set the ruleset. 'list' should be the simpleXML node formatted
according to RFC 3921 (XMPP-IM) (I.e. Node('list',{'name':listname},payload=[...]) ) according to RFC 3921 (XMPP-IM) (I.e. Node('list',{'name':listname},payload=[...]) )
Returns true on success.""" Returns true on success."""
iq=Iq('set',NS_PRIVACY,payload=[list]) iq = Iq('set', NS_PRIVACY, xmlns = '')
_on_default_response(disp, iq, cb) list_query = iq.getTag('query').setTag('list', {'name': listname})
for item in tags:
if item.has_key('type') and item.has_key('value'):
item_tag = list_query.setTag('item', {'action': item['action'],
'order': item['order'], 'type': item['type'], 'value': item['value']})
else:
item_tag = list_query.setTag('item', {'action': item['action'],
'order': item['order']})
if item.has_key('child'):
for child_tag in item['child']:
item_tag.setTag(child_tag)
_on_default_response(disp, iq, None)
def delPrivacyList(disp,listname, cb): def delPrivacyList(disp,listname):
""" Deletes privacy list 'listname'. Returns true on success.""" """ Deletes privacy list 'listname'. Returns true on success."""
iq = Iq('set',NS_PRIVACY,payload=[Node('list',{'name':listname})]) iq = Iq('set',NS_PRIVACY,payload=[Node('list',{'name':listname})])
_on_default_response(disp, iq, cb) _on_default_response(disp, iq, None)

View file

@ -249,11 +249,6 @@ class PreferencesWindow:
# try to set default font for the current desktop env # try to set default font for the current desktop env
fontbutton = self.xml.get_widget('conversation_fontbutton') fontbutton = self.xml.get_widget('conversation_fontbutton')
if font == '': if font == '':
font = gtkgui_helpers.get_default_font()
if font is not None:
font = 'Sans 10'
gajim.config.set('conversation_font', font)
fontbutton.set_font_name(font)
fontbutton.set_sensitive(False) fontbutton.set_sensitive(False)
self.xml.get_widget('default_chat_font').set_active(True) self.xml.get_widget('default_chat_font').set_active(True)
else: else:
@ -315,6 +310,8 @@ class PreferencesWindow:
commands = ('aplay', 'play', 'esdplay', 'artsplay') commands = ('aplay', 'play', 'esdplay', 'artsplay')
for command in commands: for command in commands:
if helpers.is_in_path(command): if helpers.is_in_path(command):
if command == 'aplay':
command += ' -q'
self.xml.get_widget('soundplayer_entry').set_text(command) self.xml.get_widget('soundplayer_entry').set_text(command)
gajim.config.set('soundplayer', command) gajim.config.set('soundplayer', command)
break break
@ -433,17 +430,22 @@ class PreferencesWindow:
# 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')
notify_gmail_checkbutton = self.xml.get_widget('notify_gmail_checkbutton') notify_gmail_checkbutton = self.xml.get_widget('notify_gmail_checkbutton')
notify_gmail_checkbutton.set_no_show_all(True) notify_gmail_extra_checkbutton = self.xml.get_widget('notify_gmail_extra_checkbutton')
frame_gmail.set_no_show_all(True)
for account in gajim.config.get_per('accounts'): for account in gajim.config.get_per('accounts'):
jid = gajim.get_jid_from_account(account) jid = gajim.get_jid_from_account(account)
if gajim.get_server_from_jid(jid) == 'gmail.com': if gajim.get_server_from_jid(jid) in gajim.gmail_domains:
frame_gmail.show_all()
st = gajim.config.get('notify_on_new_gmail_email') st = gajim.config.get('notify_on_new_gmail_email')
notify_gmail_checkbutton.set_active(st) notify_gmail_checkbutton.set_active(st)
notify_gmail_checkbutton.show() st = gajim.config.get('notify_on_new_gmail_email_extra')
notify_gmail_extra_checkbutton.set_active(st)
break break
else: else:
notify_gmail_checkbutton.hide() frame_gmail.hide()
self.xml.signal_autoconnect(self) self.xml.signal_autoconnect(self)
@ -839,8 +841,11 @@ class PreferencesWindow:
def on_send_os_info_checkbutton_toggled(self, widget): def on_send_os_info_checkbutton_toggled(self, widget):
self.on_checkbutton_toggled(widget, 'send_os_info') self.on_checkbutton_toggled(widget, 'send_os_info')
def on_notify_gmail_checkbutton_toggled(self, widget): def on_notify_gmail_checkbutton_toggled(self, widget):
self.on_checkbutton_toggled(widget, 'notify_on_new_gmail_email') self.on_checkbutton_toggled(widget, 'notify_on_new_gmail_email')
def on_notify_gmail_extra_checkbutton_toggled(self, widget):
self.on_checkbutton_toggled(widget, 'notify_on_new_gmail_email_extra')
def fill_msg_treeview(self): def fill_msg_treeview(self):
self.xml.get_widget('delete_msg_button').set_sensitive(False) self.xml.get_widget('delete_msg_button').set_sensitive(False)
@ -967,7 +972,6 @@ class PreferencesWindow:
path_to_snd_file = widget.get_text() path_to_snd_file = widget.get_text()
model, iter = self.sound_tree.get_selection().get_selected() model, iter = self.sound_tree.get_selection().get_selected()
model[iter][2] = path_to_snd_file # set new path to sounds_model model[iter][2] = path_to_snd_file # set new path to sounds_model
model[iter][0] = True # set the sound to enabled
def on_play_button_clicked(self, widget): def on_play_button_clicked(self, widget):
model, iter = self.sound_tree.get_selection().get_selected() model, iter = self.sound_tree.get_selection().get_selected()
@ -1313,11 +1317,13 @@ class AccountModificationWindow:
relogin_needed = False relogin_needed = False
else: # we're connected to the account we want to apply changes else: # we're connected to the account we want to apply changes
# check if relogin is needed # check if relogin is needed
relogin_needed = self.options_changed_need_relogin(config, relogin_needed = False
if self.options_changed_need_relogin(config,
('resource', 'proxy', 'usessl', 'keyname', ('resource', 'proxy', 'usessl', 'keyname',
'use_custom_host', 'custom_host')) 'use_custom_host', 'custom_host')):
relogin_needed = True
if config['use_custom_host'] and (self.option_changed(config, elif config['use_custom_host'] and (self.option_changed(config,
'custom_host') or self.option_changed(config, 'custom_port')): 'custom_host') or self.option_changed(config, 'custom_port')):
relogin_needed = True relogin_needed = True

View file

@ -83,6 +83,14 @@ class ConversationTextview:
color = gajim.config.get('statusmsgcolor') color = gajim.config.get('statusmsgcolor')
self.tagStatus.set_property('foreground', color) self.tagStatus.set_property('foreground', color)
colors = gajim.config.get('gc_nicknames_colors')
colors = colors.split(':')
for color in xrange(len(colors)):
tagname = 'gc_nickname_color_' + str(color)
tag = buffer.create_tag(tagname)
color = colors[color]
tag.set_property('foreground', color)
tag = buffer.create_tag('marked') tag = buffer.create_tag('marked')
color = gajim.config.get('markedmsgcolor') color = gajim.config.get('markedmsgcolor')
tag.set_property('foreground', color) tag.set_property('foreground', color)
@ -568,9 +576,6 @@ class ConversationTextview:
other_tags_for_name = [], other_tags_for_time = [], other_tags_for_name = [], other_tags_for_time = [],
other_tags_for_text = [], subject = None, old_kind = None): other_tags_for_text = [], subject = None, old_kind = None):
'''prints 'chat' type messages''' '''prints 'chat' type messages'''
# kind = info, we print things as if it was a status: same color, ...
if kind == 'info':
kind = 'status'
buffer = self.tv.get_buffer() buffer = self.tv.get_buffer()
buffer.begin_user_action() buffer.begin_user_action()
end_iter = buffer.get_end_iter() end_iter = buffer.get_end_iter()
@ -589,7 +594,7 @@ class ConversationTextview:
# We don't have tim for outgoing messages... # We don't have tim for outgoing messages...
tim = time.localtime() tim = time.localtime()
current_print_time = gajim.config.get('print_time') current_print_time = gajim.config.get('print_time')
if current_print_time == 'always': if current_print_time == 'always' and kind != 'info':
before_str = gajim.config.get('before_time') before_str = gajim.config.get('before_time')
after_str = gajim.config.get('after_time') after_str = gajim.config.get('after_time')
# get difference in days since epoch (86400 = 24*3600) # get difference in days since epoch (86400 = 24*3600)
@ -613,7 +618,7 @@ class ConversationTextview:
tim_format = time.strftime(format, tim).encode('utf-8') tim_format = time.strftime(format, tim).encode('utf-8')
buffer.insert_with_tags_by_name(end_iter, tim_format + ' ', buffer.insert_with_tags_by_name(end_iter, tim_format + ' ',
*other_tags_for_time) *other_tags_for_time)
elif current_print_time == 'sometimes': elif current_print_time == 'sometimes' and kind != 'info':
every_foo_seconds = 60 * gajim.config.get( every_foo_seconds = 60 * gajim.config.get(
'print_ichat_every_foo_minutes') 'print_ichat_every_foo_minutes')
seconds_passed = time.mktime(tim) - self.last_time_printout seconds_passed = time.mktime(tim) - self.last_time_printout
@ -631,6 +636,9 @@ class ConversationTextview:
buffer.insert_with_tags_by_name(end_iter, tim_format + '\n', buffer.insert_with_tags_by_name(end_iter, tim_format + '\n',
'time_sometimes') 'time_sometimes')
# kind = info, we print things as if it was a status: same color, ...
if kind == 'info':
kind = 'status'
other_text_tag = self.detect_other_text_tag(text, kind) other_text_tag = self.detect_other_text_tag(text, kind)
text_tags = other_tags_for_text[:] # create a new list text_tags = other_tags_for_text[:] # create a new list
if other_text_tag: if other_text_tag:

File diff suppressed because it is too large Load diff

View file

@ -453,20 +453,21 @@ class Interface:
gajim.connections[account].remove_transfers_for_contact(contact1) gajim.connections[account].remove_transfers_for_contact(contact1)
self.roster.chg_contact_status(contact1, array[1], status_message, self.roster.chg_contact_status(contact1, array[1], status_message,
account) account)
# play sound # Notifications
if old_show < 2 and new_show > 1: if old_show < 2 and new_show > 1:
notify.notify('contact_connected', jid, account, status_message) notify.notify('contact_connected', jid, account, status_message)
if self.remote_ctrl: if self.remote_ctrl:
self.remote_ctrl.raise_signal('ContactPresence', self.remote_ctrl.raise_signal('ContactPresence',
(account, array)) (account, array))
elif old_show > 1 and new_show < 2: elif old_show > 1 and new_show < 2:
notify.notify('contact_disconnected', jid, account, status_message) notify.notify('contact_disconnected', jid, account, status_message)
if self.remote_ctrl: if self.remote_ctrl:
self.remote_ctrl.raise_signal('ContactAbsence', (account, array)) self.remote_ctrl.raise_signal('ContactAbsence', (account, array))
# FIXME: stop non active file transfers # FIXME: stop non active file transfers
elif new_show > 1: # Status change (not connected/disconnected or error (<1)) elif new_show > 1: # Status change (not connected/disconnected or error (<1))
notify.notify('status_change', jid, account, [new_show, status_message]) notify.notify('status_change', jid, account, [new_show,
status_message])
else: else:
# FIXME: Msn transport (CMSN1.2.1 and PyMSN0.10) doesn't follow the JEP # FIXME: Msn transport (CMSN1.2.1 and PyMSN0.10) doesn't follow the JEP
# remove in 2007 # remove in 2007
@ -567,7 +568,8 @@ class Interface:
msg_type, array[5], resource, msg_id, array[9]) msg_type, array[5], resource, msg_id, array[9])
nickname = gajim.get_name_from_jid(account, jid) nickname = gajim.get_name_from_jid(account, jid)
# Check and do wanted notifications # Check and do wanted notifications
notify.notify('new_message', jid, account, [msg_type, first, nickname, message]) notify.notify('new_message', jid, account, [msg_type, first, nickname,
message])
if self.remote_ctrl: if self.remote_ctrl:
self.remote_ctrl.raise_signal('NewMessage', (account, array)) self.remote_ctrl.raise_signal('NewMessage', (account, array))
@ -800,7 +802,7 @@ class Interface:
c = gajim.contacts.get_contact(account, array[0], array[1]) c = gajim.contacts.get_contact(account, array[0], array[1])
# c is a list when no resource is given. it probably means that contact # c is a list when no resource is given. it probably means that contact
# is offline, so only on Contact instance # is offline, so only on Contact instance
if isinstance(c, list): if isinstance(c, list) and len(c):
c = c[0] c = c[0]
if c: # c can be none if it's a gc contact if c: # c can be none if it's a gc contact
c.last_status_time = time.localtime(time.time() - array[2]) c.last_status_time = time.localtime(time.time() - array[2])
@ -1026,12 +1028,20 @@ class Interface:
def handle_event_gmail_notify(self, account, array): def handle_event_gmail_notify(self, account, array):
jid = array[0] jid = array[0]
gmail_new_messages = int(array[1]) gmail_new_messages = int(array[1])
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 'single_msg_recv.png') #FIXME: find a better image
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)
if gajim.config.get('notify_on_new_gmail_email_extra'):
for gmessage in gmail_messages_list:
# each message has a 'From', 'Subject' and 'Snippet' field
text += _('\nFrom: %(from_address)s') % \
{'from_address': gmessage['From']}
path = gtkgui_helpers.get_path_to_generic_or_avatar(img) path = gtkgui_helpers.get_path_to_generic_or_avatar(img)
notify.popup(_('New E-mail'), jid, account, 'gmail', notify.popup(_('New E-mail'), jid, account, 'gmail',
path_to_image = path, title = title, text = text) path_to_image = path, title = title, text = text)
@ -1328,6 +1338,31 @@ class Interface:
def handle_event_metacontacts(self, account, tags_list): def handle_event_metacontacts(self, account, tags_list):
gajim.contacts.define_metacontacts(account, tags_list) gajim.contacts.define_metacontacts(account, tags_list)
def handle_event_privacy_lists_received(self, account, data):
# ('PRIVACY_LISTS_RECEIVED', account, list)
if not self.instances.has_key(account):
return
if self.instances[account].has_key('privacy_lists'):
self.instances[account]['privacy_lists'].privacy_lists_received(data)
def handle_event_privacy_list_received(self, account, data):
# ('PRIVACY_LISTS_RECEIVED', account, (name, rules))
if not self.instances.has_key(account):
return
name = data[0]
rules = data[1]
if self.instances[account].has_key('privacy_list_%s' % name):
self.instances[account]['privacy_list_%s' % name].\
privacy_list_received(rules)
def handle_event_privacy_lists_active_default(self, account, data):
if not data:
return
# Send to all privacy_list_* windows as we can't know which one asked
for win in self.instances[account]:
if win.startswith('privacy_list_'):
self.instances[account][win].check_active_default(data)
def read_sleepy(self): def read_sleepy(self):
'''Check idle status and change that status if needed''' '''Check idle status and change that status if needed'''
if not self.sleeper.poll(): if not self.sleeper.poll():
@ -1628,6 +1663,10 @@ class Interface:
'ASK_NEW_NICK': self.handle_event_ask_new_nick, 'ASK_NEW_NICK': self.handle_event_ask_new_nick,
'SIGNED_IN': self.handle_event_signed_in, 'SIGNED_IN': self.handle_event_signed_in,
'METACONTACTS': self.handle_event_metacontacts, 'METACONTACTS': self.handle_event_metacontacts,
'PRIVACY_LISTS_RECEIVED': self.handle_event_privacy_lists_received,
'PRIVACY_LIST_RECEIVED': self.handle_event_privacy_list_received,
'PRIVACY_LISTS_ACTIVE_DEFAULT': \
self.handle_event_privacy_lists_active_default,
} }
gajim.handlers = self.handlers gajim.handlers = self.handlers

View file

@ -503,6 +503,9 @@ class GroupchatControl(ChatControlBase):
fin = True fin = True
return None return None
gc_count_nicknames_colors = 0
gc_custom_colors = {}
def print_conversation(self, text, contact = '', tim = None): def print_conversation(self, text, contact = '', tim = None):
'''Print a line in the conversation: '''Print a line in the conversation:
if contact is set: it's a message from someone or an info message (contact if contact is set: it's a message from someone or an info message (contact
@ -528,6 +531,18 @@ class GroupchatControl(ChatControlBase):
if kind == 'incoming': # it's a message NOT from us if kind == 'incoming': # it's a message NOT from us
# highlighting and sounds # highlighting and sounds
(highlight, sound) = self.highlighting_for_message(text, tim) (highlight, sound) = self.highlighting_for_message(text, tim)
gc_class=self.__class__
if gc_class.gc_custom_colors.has_key(contact):
other_tags_for_name.append('gc_nickname_color_' + \
str(gc_class.gc_custom_colors[contact]))
else:
gc_class.gc_count_nicknames_colors += 1
gc_class.gc_custom_colors[contact] = gc_class.gc_count_nicknames_colors
other_tags_for_name.append('gc_nickname_color_' + \
str(gc_class.gc_count_nicknames_colors))
number_of_colors = len(gajim.config.get('gc_nicknames_colors').split(':'))
if gc_class.gc_count_nicknames_colors == number_of_colors:
gc_class.gc_count_nicknames_colors = 0
if highlight: if highlight:
# muc-specific chatstate # muc-specific chatstate
self.parent_win.redraw_tab(self, 'attention') self.parent_win.redraw_tab(self, 'attention')

View file

@ -19,6 +19,7 @@
import xml.sax.saxutils import xml.sax.saxutils
import gtk import gtk
import gtk.glade
import gobject import gobject
import pango import pango
import os import os
@ -41,6 +42,9 @@ from common import i18n
from common import gajim from common import gajim
from common import helpers from common import helpers
gtk.glade.bindtextdomain(i18n.APP, i18n.DIR)
gtk.glade.textdomain(i18n.APP)
screen_w = gtk.gdk.screen_width() screen_w = gtk.gdk.screen_width()
screen_h = gtk.gdk.screen_height() screen_h = gtk.gdk.screen_height()

View file

@ -27,13 +27,13 @@ import gtk
import time import time
import locale import locale
from common import i18n
import exceptions import exceptions
import dialogs import dialogs
import gtkgui_helpers import gtkgui_helpers
from common.logger import LOG_DB_PATH, constants from common.logger import LOG_DB_PATH, constants
from common import gajim from common import gajim
from common import i18n
from common import helpers from common import helpers
# time, message, subject # time, message, subject

View file

@ -143,8 +143,7 @@ def notify(event, jid, account, parameters):
text = message text = message
elif message_type == 'pm': # private message elif message_type == 'pm': # private message
event_type = _('New Private Message') event_type = _('New Private Message')
room_name, t = gajim.get_room_name_and_server_from_room_jid( room_name, t = gajim.get_room_name_and_server_from_room_jid(jid)
jid)
img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
'priv_msg_recv.png') 'priv_msg_recv.png')
title = _('New Private Message from room %s') % room_name title = _('New Private Message from room %s') % room_name
@ -156,7 +155,7 @@ def notify(event, jid, account, parameters):
'chat_msg_recv.png') 'chat_msg_recv.png')
title = _('New Message from %(nickname)s') % \ title = _('New Message from %(nickname)s') % \
{'nickname': nickname} {'nickname': nickname}
text = message text = message
path = gtkgui_helpers.get_path_to_generic_or_avatar(img) path = gtkgui_helpers.get_path_to_generic_or_avatar(img)
popup(event_type, jid, account, message_type, popup(event_type, jid, account, message_type,
path_to_image = path, title = title, text = text) path_to_image = path, title = title, text = text)
@ -167,8 +166,8 @@ def notify(event, jid, account, parameters):
helpers.play_sound('first_message_received') helpers.play_sound('first_message_received')
else: else:
helpers.play_sound('next_message_received') helpers.play_sound('next_message_received')
elif (event == 'contact_connected' or event == 'contact_disconnected'): elif event in ('contact_connected', 'contact_disconnected'):
helpers.play_sound(event) helpers.play_sound(event)
def popup(event_type, jid, account, msg_type = '', path_to_image = None, def popup(event_type, jid, account, msg_type = '', path_to_image = None,

View file

@ -240,10 +240,11 @@ class SignalObject(DbusPrototype):
send file, located at 'file_path' to 'jid', using account send file, located at 'file_path' to 'jid', using account
(optional) 'account' ''' (optional) 'account' '''
file_path, jid, account = self._get_real_arguments(args, 3) file_path, jid, account = self._get_real_arguments(args, 3)
connected_account, contact = self.get_account_and_contact(account, jid) connected_account, contact = self.get_account_and_contact(account, jid)
if connected_account: if connected_account:
if file_path[:7] == 'file://':
file_path=file_path[7:]
if os.path.isfile(file_path): # is it file? if os.path.isfile(file_path): # is it file?
gajim.interface.instances['file_transfers'].send_file( gajim.interface.instances['file_transfers'].send_file(
connected_account, contact, file_path) connected_account, contact, file_path)

View file

@ -238,9 +238,8 @@ class RosterWindow:
if family: if family:
for data in family: for data in family:
_account = data['account'] _account = data['account']
#XXX When we support metacontacts from different servers, make # Metacontacts over different accounts only in merged mode
# sure that loop from #1953 is fixed and remove next 2 lines! if _account != account and not self.regroup:
if _account != account:
continue continue
_jid = data['jid'] _jid = data['jid']
@ -274,7 +273,8 @@ class RosterWindow:
if (contact.show in ('offline', 'error') or hide) and \ if (contact.show in ('offline', 'error') or hide) and \
not showOffline and (not _('Transports') in contact.groups or \ not showOffline and (not _('Transports') in contact.groups or \
gajim.connections[account].connected < 2) and \ gajim.connections[account].connected < 2) and \
not gajim.awaiting_events[account].has_key(jid): not gajim.awaiting_events[account].has_key(jid) and \
not _('Not in Roster') in contact.groups:
return return
# Remove brother contacts that are already in roster to add them # Remove brother contacts that are already in roster to add them
@ -333,6 +333,9 @@ class RosterWindow:
gajim.interface.roster.add_contact_to_roster(transport, account) gajim.interface.roster.add_contact_to_roster(transport, account)
def really_remove_contact(self, contact, account): def really_remove_contact(self, contact, account):
if not gajim.interface.instances.has_key(account):
# Account has been deleted during the timeout that called us
return
if contact.jid in gajim.newly_added[account]: if contact.jid in gajim.newly_added[account]:
return return
if contact.jid.find('@') < 1 and gajim.connections[account].connected > 1: if contact.jid.find('@') < 1 and gajim.connections[account].connected > 1:
@ -475,15 +478,18 @@ class RosterWindow:
if icon_name in ('error', 'offline'): if icon_name in ('error', 'offline'):
# get the icon from the first child as they are sorted by show # get the icon from the first child as they are sorted by show
child_jid = model[child_iter][C_JID].decode('utf-8') child_jid = model[child_iter][C_JID].decode('utf-8')
child_account = model[child_iter][C_ACCOUNT].decode('utf-8')
child_contact = gajim.contacts.get_contact_with_highest_priority( child_contact = gajim.contacts.get_contact_with_highest_priority(
account, child_jid) child_account, child_jid)
child_icon_name = helpers.get_icon_name_to_show(child_contact, account) child_icon_name = helpers.get_icon_name_to_show(child_contact,
child_account)
if child_icon_name not in ('error', 'not in roster'): if child_icon_name not in ('error', 'not in roster'):
icon_name = child_icon_name icon_name = child_icon_name
while child_iter: while child_iter:
# a child has awaiting messages ? # a child has awaiting messages ?
child_jid = model[child_iter][C_JID].decode('utf-8') child_jid = model[child_iter][C_JID].decode('utf-8')
if gajim.awaiting_events[account].has_key(child_jid): child_account = model[child_iter][C_ACCOUNT].decode('utf-8')
if gajim.awaiting_events[child_account].has_key(child_jid):
icon_name = 'message' icon_name = 'message'
break break
child_iter = model.iter_next(child_iter) child_iter = model.iter_next(child_iter)
@ -582,6 +588,13 @@ class RosterWindow:
gajim.interface.instances[account]['xml_console'] = \ gajim.interface.instances[account]['xml_console'] = \
dialogs.XMLConsoleWindow(account) dialogs.XMLConsoleWindow(account)
def on_privacy_lists_menuitem_activate(self, widget, account):
if gajim.interface.instances[account].has_key('privacy_lists'):
gajim.interface.instances[account]['privacy_lists'].window.present()
else:
gajim.interface.instances[account]['privacy_lists'] = \
dialogs.PrivacyListsWindow(account)
def on_set_motd_menuitem_activate(self, widget, account): def on_set_motd_menuitem_activate(self, widget, account):
server = gajim.config.get_per('accounts', account, 'hostname') server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/motd' server += '/announce/motd'
@ -617,6 +630,7 @@ class RosterWindow:
send_single_message_menuitem = xml.get_widget( send_single_message_menuitem = xml.get_widget(
'send_single_message_menuitem') 'send_single_message_menuitem')
xml_console_menuitem = xml.get_widget('xml_console_menuitem') xml_console_menuitem = xml.get_widget('xml_console_menuitem')
privacy_lists_menuitem = xml.get_widget('privacy_lists_menuitem')
administrator_menuitem = xml.get_widget('administrator_menuitem') administrator_menuitem = xml.get_widget('administrator_menuitem')
send_server_message_menuitem = xml.get_widget( send_server_message_menuitem = xml.get_widget(
'send_server_message_menuitem') 'send_server_message_menuitem')
@ -630,6 +644,9 @@ class RosterWindow:
xml_console_menuitem.connect('activate', xml_console_menuitem.connect('activate',
self.on_xml_console_menuitem_activate, account) self.on_xml_console_menuitem_activate, account)
privacy_lists_menuitem.connect('activate',
self.on_privacy_lists_menuitem_activate, account)
send_server_message_menuitem.connect('activate', send_server_message_menuitem.connect('activate',
self.on_send_server_message_menuitem_activate, account) self.on_send_server_message_menuitem_activate, account)
@ -1796,14 +1813,26 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
for c in gajim.contacts.get_contact(account, contact.jid): for c in gajim.contacts.get_contact(account, contact.jid):
self.remove_contact(c, account) self.remove_contact(c, account)
gajim.contacts.remove_jid(account, c.jid) gajim.contacts.remove_jid(account, c.jid)
need_readd = False
if not remove_auth and contact.sub == 'both': if not remove_auth and contact.sub == 'both':
contact.name = '' contact.name = ''
contact.groups = [] contact.groups = []
contact.sub = 'from' contact.sub = 'from'
gajim.contacts.add_contact(account, contact) gajim.contacts.add_contact(account, contact)
self.add_contact_to_roster(contact.jid, account) self.add_contact_to_roster(contact.jid, account)
elif gajim.interface.msg_win_mgr.has_window(contact.jid, account) or \ elif gajim.awaiting_events[account].has_key(contact.jid):
gajim.awaiting_events[account].has_key(contact.jid): need_readd = True
elif gajim.interface.msg_win_mgr.has_window(contact.jid, account):
if _('Not in Roster') in contact.groups:
# Close chat window
msg_win = gajim.interface.msg_win_mgr.get_window(contact.jid,
account)
ctrl = gajim.interface.msg_win_mgr.get_control(contact.jid,
account)
msg_win.remove_tab(ctrl)
else:
need_readd = True
if need_readd:
c = gajim.contacts.create_contact(jid = contact.jid, c = gajim.contacts.create_contact(jid = contact.jid,
name = '', groups = [_('Not in Roster')], name = '', groups = [_('Not in Roster')],
show = 'not in roster', status = '', ask = 'none', show = 'not in roster', status = '', ask = 'none',
@ -3045,30 +3074,32 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
data = model[iter][C_JID] data = model[iter][C_JID]
selection.set(selection.target, 8, data) selection.set(selection.target, 8, data)
def on_drop_in_contact(self, widget, account, c_source, c_dest, def on_drop_in_contact(self, widget, account_source, c_source, account_dest,
was_big_brother, context, etime): c_dest, was_big_brother, context, etime):
# children must take the new tag too, so remember old tag # children must take the new tag too, so remember old tag
old_tag = gajim.contacts.get_metacontacts_tag(account, c_source.jid) old_tag = gajim.contacts.get_metacontacts_tag(account_source,
c_source.jid)
# remove the source row # remove the source row
self.remove_contact(c_source, account) self.remove_contact(c_source, account_source)
# brother inherite big brother groups # brother inherite big brother groups
c_source.groups = [] c_source.groups = []
for g in c_dest.groups: for g in c_dest.groups:
c_source.groups.append(g) c_source.groups.append(g)
gajim.contacts.add_metacontact(account, c_dest.jid, account, c_source.jid) gajim.contacts.add_metacontact(account_dest, c_dest.jid, account_source,
c_source.jid)
if was_big_brother: if was_big_brother:
# add brothers too # add brothers too
all_jid = gajim.contacts.get_metacontacts_jids(old_tag) all_jid = gajim.contacts.get_metacontacts_jids(old_tag)
for _account in all_jid: for _account in all_jid:
for _jid in all_jid[_account]: for _jid in all_jid[_account]:
gajim.contacts.add_metacontact(account, c_dest.jid, _account, gajim.contacts.add_metacontact(account_dest, c_dest.jid,
_jid) _account, _jid)
_c = gajim.contacts.get_first_contact_from_jid(_account, _jid) _c = gajim.contacts.get_first_contact_from_jid(_account, _jid)
self.remove_contact(_c, _account) self.remove_contact(_c, _account)
self.add_contact_to_roster(_jid, _account) self.add_contact_to_roster(_jid, _account)
self.draw_contact(_jid, _account) self.draw_contact(_jid, _account)
self.add_contact_to_roster(c_source.jid, account) self.add_contact_to_roster(c_source.jid, account_source)
self.draw_contact(c_dest.jid, account) self.draw_contact(c_dest.jid, account_dest)
context.finish(True, True, etime) context.finish(True, True, etime)
@ -3117,10 +3148,10 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
iter_dest = model.get_iter(path_dest) iter_dest = model.get_iter(path_dest)
type_dest = model[iter_dest][C_TYPE].decode('utf-8') type_dest = model[iter_dest][C_TYPE].decode('utf-8')
jid_dest = model[iter_dest][C_JID].decode('utf-8') jid_dest = model[iter_dest][C_JID].decode('utf-8')
account = model[iter_dest][C_ACCOUNT].decode('utf-8') account_dest = model[iter_dest][C_ACCOUNT].decode('utf-8')
# if account is not connected, do nothing # if account is not connected, do nothing
if gajim.connections[account].connected < 2: if gajim.connections[account_dest].connected < 2:
return return
if info == self.TARGET_TYPE_URI_LIST: if info == self.TARGET_TYPE_URI_LIST:
@ -3129,15 +3160,15 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
return return
if type_dest != 'contact': if type_dest != 'contact':
return return
c_dest = gajim.contacts.get_contact_with_highest_priority(account, c_dest = gajim.contacts.get_contact_with_highest_priority(account_dest,
jid_dest) jid_dest)
uri = data.strip() uri = data.strip()
uri_splitted = uri.split() # we may have more than one file dropped uri_splitted = uri.split() # we may have more than one file dropped
for uri in uri_splitted: for uri in uri_splitted:
path = helpers.get_file_path_from_dnd_dropped_uri(uri) path = helpers.get_file_path_from_dnd_dropped_uri(uri)
if os.path.isfile(path): # is it file? if os.path.isfile(path): # is it file?
gajim.interface.instances['file_transfers'].send_file(account, gajim.interface.instances['file_transfers'].send_file(
c_dest, path) account_dest, c_dest, path)
return return
if position == gtk.TREE_VIEW_DROP_BEFORE and len(path_dest) == 2: if position == gtk.TREE_VIEW_DROP_BEFORE and len(path_dest) == 2:
@ -3146,19 +3177,11 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
iter_source = treeview.get_selection().get_selected()[1] iter_source = treeview.get_selection().get_selected()[1]
path_source = model.get_path(iter_source) path_source = model.get_path(iter_source)
type_source = model[iter_source][C_TYPE] type_source = model[iter_source][C_TYPE]
if type_dest == 'account': # dropped on an account account_source = model[iter_source][C_ACCOUNT].decode('utf-8')
return
if type_source != 'contact': # source is not a contact if type_source != 'contact': # source is not a contact
return return
source_account = model[iter_source][C_ACCOUNT].decode('utf-8') if type_dest == 'account' and account_source == account_dest:
disable_meta = False return
if account != source_account: # dropped in another account
if self.regroup:
# in merge mode it is ok to change group, but disable meta
account = source_account
disable_meta = True
else:
return
it = iter_source it = iter_source
while model[it][C_TYPE] == 'contact': while model[it][C_TYPE] == 'contact':
it = model.iter_parent(it) it = model.iter_parent(it)
@ -3167,36 +3190,47 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
if grp_source in helpers.special_groups: if grp_source in helpers.special_groups:
return return
jid_source = data.decode('utf-8') jid_source = data.decode('utf-8')
c_source = gajim.contacts.get_contact_with_highest_priority(account, c_source = gajim.contacts.get_contact_with_highest_priority(
jid_source) account_source, jid_source)
# Get destination group
grp_dest = None
if type_dest == 'group': if type_dest == 'group':
grp_dest = model[iter_dest][C_JID].decode('utf-8') grp_dest = model[iter_dest][C_JID].decode('utf-8')
if grp_dest in helpers.special_groups: elif type_dest in ('contact', 'agent'):
return
if context.action == gtk.gdk.ACTION_COPY:
self.on_drop_in_group(None, account, c_source, grp_dest, context,
etime)
return
self.on_drop_in_group(None, account, c_source, grp_dest, context,
etime, grp_source)
return
else:
it = iter_dest it = iter_dest
while model[it][C_TYPE] != 'group': while model[it][C_TYPE] != 'group':
it = model.iter_parent(it) it = model.iter_parent(it)
grp_dest = model[it][C_JID].decode('utf-8') grp_dest = model[it][C_JID].decode('utf-8')
if (type_dest == 'account' or not self.regroup) and \
account_source != account_dest:
# add contact to this account in that group
dialogs.AddNewContactWindow(account = account_dest, jid = jid_source,
user_nick = c_source.name, group = grp_dest)
return
# Get destination group
if type_dest == 'group':
if grp_dest in helpers.special_groups:
return
if context.action == gtk.gdk.ACTION_COPY:
self.on_drop_in_group(None, account_source, c_source, grp_dest,
context, etime)
return
self.on_drop_in_group(None, account_source, c_source, grp_dest,
context, etime, grp_source)
return
if grp_dest in helpers.special_groups: if grp_dest in helpers.special_groups:
return return
if jid_source == jid_dest: if jid_source == jid_dest:
if grp_source == grp_dest: if grp_source == grp_dest and account_source == account_dest:
return return
if context.action == gtk.gdk.ACTION_COPY: if context.action == gtk.gdk.ACTION_COPY:
self.on_drop_in_group(None, account, c_source, grp_dest, context, self.on_drop_in_group(None, account_source, c_source, grp_dest,
etime) context, etime)
return return
self.on_drop_in_group(None, account, c_source, grp_dest, context, self.on_drop_in_group(None, account_source, c_source, grp_dest,
etime, grp_source) context, etime, grp_source)
return return
if grp_source == grp_dest: if grp_source == grp_dest:
# Add meta contact # Add meta contact
@ -3205,7 +3239,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
# if context.action == gtk.gdk.ACTION_COPY: # if context.action == gtk.gdk.ACTION_COPY:
# # Keep only MOVE # # Keep only MOVE
# return # return
c_dest = gajim.contacts.get_contact_with_highest_priority(account, c_dest = gajim.contacts.get_contact_with_highest_priority(account_dest,
jid_dest) jid_dest)
is_big_brother = False is_big_brother = False
if model.iter_has_child(iter_source): if model.iter_has_child(iter_source):
@ -3213,35 +3247,30 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
if not c_dest: if not c_dest:
# c_dest is None if jid_dest doesn't belong to account # c_dest is None if jid_dest doesn't belong to account
return return
self.on_drop_in_contact(treeview, account, c_source, c_dest, self.on_drop_in_contact(treeview, account_source, c_source,
is_big_brother, context, etime) account_dest, c_dest, is_big_brother, context, etime)
return return
# We upgrade only the first user because user2.groups is a pointer to # We upgrade only the first user because user2.groups is a pointer to
# user1.groups # user1.groups
if context.action == gtk.gdk.ACTION_COPY: if context.action == gtk.gdk.ACTION_COPY:
self.on_drop_in_group(None, account, c_source, grp_dest, context, self.on_drop_in_group(None, account_source, c_source, grp_dest,
etime) context, etime)
else: else:
menu = gtk.Menu() menu = gtk.Menu()
item = gtk.MenuItem(_('Drop %s in group %s') % (c_source.name, item = gtk.MenuItem(_('Drop %s in group %s') % (c_source.name,
grp_dest)) grp_dest))
item.connect('activate', self.on_drop_in_group, account, c_source, item.connect('activate', self.on_drop_in_group, account_dest, c_source,
grp_dest, context, etime, grp_source) grp_dest, context, etime, grp_source)
menu.append(item) menu.append(item)
if not disable_meta: c_dest = gajim.contacts.get_contact_with_highest_priority(
# source and dest account are the same, enable metacontacts account_dest, jid_dest)
c_dest = gajim.contacts.get_contact_with_highest_priority(account, item = gtk.MenuItem(_('Make %s and %s metacontacts') % (c_source.name,
jid_dest) c_dest.name))
item = gtk.MenuItem(_('Make %s and %s metacontacts') % (c_source.name, is_big_brother = False
c_dest.name)) if model.iter_has_child(iter_source):
is_big_brother = False is_big_brother = True
if model.iter_has_child(iter_source): item.connect('activate', self.on_drop_in_contact, account_source,
is_big_brother = True c_source, account_dest, c_dest, is_big_brother, context, etime)
item.connect('activate', self.on_drop_in_contact, account, c_source,
c_dest, is_big_brother, context, etime)
else: #source and dest account are not the same, disable meta
item = gtk.MenuItem(_('Can\'t create a metacontact with contacts from two different accounts'))
item.set_sensitive(False)
menu.append(item) menu.append(item)

View file

@ -388,8 +388,9 @@ class GCTooltip(BaseTooltip):
if contact.jid.strip() != '': if contact.jid.strip() != '':
jid_markup = '<span weight="bold">' + contact.jid + '</span>' jid_markup = '<span weight="bold">' + contact.jid + '</span>'
else: else:
jid_markup = '<span weight="bold">' + contact.get_shown_name() + \ jid_markup = '<span weight="bold">' + \
'</span>' gtkgui_helpers.escape_for_pango_markup(contact.get_shown_name()) \
+ '</span>'
properties.append((jid_markup, None)) properties.append((jid_markup, None))
properties.append((_('Role: '), helpers.get_uf_role(contact.role))) properties.append((_('Role: '), helpers.get_uf_role(contact.role)))
properties.append((_('Affiliation: '), contact.affiliation.capitalize())) properties.append((_('Affiliation: '), contact.affiliation.capitalize()))

View file

@ -270,6 +270,8 @@ class VcardWindow:
self.fill_status_label() self.fill_status_label()
def set_os_info(self, resource, client_info, os_info): def set_os_info(self, resource, client_info, os_info):
if self.xml.get_widget('information_notebook').get_n_pages() < 5:
return
i = 0 i = 0
client = '' client = ''
os = '' os = ''
@ -293,6 +295,8 @@ class VcardWindow:
self.xml.get_widget('os_label').set_text(os) self.xml.get_widget('os_label').set_text(os)
def fill_status_label(self): def fill_status_label(self):
if self.xml.get_widget('information_notebook').get_n_pages() < 5:
return
contact_list = gajim.contacts.get_contact(self.account, self.contact.jid) contact_list = gajim.contacts.get_contact(self.account, self.contact.jid)
# stats holds show and status message # stats holds show and status message
stats = '' stats = ''