Ejemplo n.º 1
0
    def __init__(self, community_gui, gui, com):
        GUI_Page.__init__(self, com.get('name'))

        self.notification = get_plugin_by_type(PLUGIN_TYPE_NOTIFICATION)
        self.community = get_plugin_by_type(PLUGIN_TYPE_COMMUNITY)

        self.item_double_clicking = None
        self.community_gui = community_gui
        self.main_gui = gui
        self.com = com

        self.list_view = community_gui.list_view_setting.value

        self.profile_widgets = {}

        # model (icon, item, text)
        self.itemlist = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_PYOBJECT, str, str)
        self.update_members()

        self.pic_dialog = Picture_Choose_Dialog(gui, self.got_picture)

        self.notebook = gtk.Notebook()
        self.notebook.set_show_tabs(True)
        self.notebook.set_show_border(False)
        self.initialize_members_page()
        self.initialize_profile_page()
        self.initialize_modify_page()
        self.pack_start(self.notebook)
Ejemplo n.º 2
0
    def __init__(self, gui, user):
        """User_Page class is for showing user's profile information
        defined in the Edit Profile dialog and for showing user's
        communities.

        update_user_page() have to be called after user's profile
        is changed or after user's communities are changed so that
        new values are loaded into GUI"""

        GUI_Page.__init__(self, 'My profile')
        # references to gui components which text or other
        # attribute will be modified if user's profile changes
        self.profile_widgets = {}

        self.main_gui = gui
        self.user = user

        self.community = get_plugin_by_type(PLUGIN_TYPE_COMMUNITY)

        self.initialize_profile_page_widgets()

        self.pic_dialog = Picture_Choose_Dialog(self.main_gui, self.got_picture)
Ejemplo n.º 3
0
    def __init__(self, title, gui):
        self.main_gui = gui
        self.personal_community = False

        self.icon_fname = None
        self.icon_changed = False
        self.notification = get_plugin_by_type(PLUGIN_TYPE_NOTIFICATION)
        self.community = get_plugin_by_type(PLUGIN_TYPE_COMMUNITY)

        self.main_window = gui.get_main_window()

        new_title = title + ' Community'
        self.dialog = gtk.Dialog(new_title, self.main_window, \
                                 gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL, \
                                 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, \
                                  title, gtk.RESPONSE_OK))
        # this should be better for toplevel windows than set_size_request()
        self.dialog.set_default_size(400, 300)

        self.initialize_widgets()
        self.dialog.connect("response", self.response_handler)
        self.dialog.show_all()

        self.pic_dialog = Picture_Choose_Dialog(self.main_gui, self.got_picture)
Ejemplo n.º 4
0
class My_User_Page(GUI_Page):

    def __init__(self, gui, user):
        """User_Page class is for showing user's profile information
        defined in the Edit Profile dialog and for showing user's
        communities.

        update_user_page() have to be called after user's profile
        is changed or after user's communities are changed so that
        new values are loaded into GUI"""

        GUI_Page.__init__(self, 'My profile')
        # references to gui components which text or other
        # attribute will be modified if user's profile changes
        self.profile_widgets = {}

        self.main_gui = gui
        self.user = user

        self.community = get_plugin_by_type(PLUGIN_TYPE_COMMUNITY)

        self.initialize_profile_page_widgets()

        self.pic_dialog = Picture_Choose_Dialog(self.main_gui, self.got_picture)

    def update_user_page(self):
        """ Function calls other functions to update user's
        profile, community, content and plugin pages. """

        self.update_profile_widgets()
        
    def update_profile_widgets(self):
        """ Reads new profile information from user and
        updates profile page's widgets."""
        
        image = get_user_profile_picture(self.user)
        self.profile_image.set_from_pixbuf(image)

    def initialize_profile_page_widgets(self):
        
        self.profile_main_vbox = gtk.VBox()
        swindow = new_scrollarea()
        swindow.set_border_width(0)

        main_hbox = gtk.HBox(False, 20)

        picture_vbox = gtk.VBox()

        self.profile_image = gtk.Image()
        self.profile_image.set_size_request(MAX_FACE_DIMENSION+10, MAX_FACE_DIMENSION+10)

        eventbox = gtk.EventBox()
        eventbox.connect("button-press-event", self.image_clicked)
        eventbox.add(self.profile_image)
        picture_vbox.pack_start(gtk.Label('Click picture to change'))
        picture_vbox.pack_start(eventbox, True, True)

        # User always has a nick
        widget = gtk.Entry()
        widget.set_text(self.user.get('nick'))
        widget.connect("focus-out-event", self.entry_focus_out, 'nick')
        self.profile_widgets['nick'] = widget
        nick_label = gtk.Label('Nick:')
        nick_label.set_alignment(0, 0)
        picture_vbox.pack_start(nick_label, False, False)
        picture_vbox.pack_start(widget, False, False)

        left_hbox = gtk.VBox(False, 20)
        left_hbox.pack_start(picture_vbox, False, False)

        user_info_vbox = gtk.VBox(False, 5)

        profile_components = (('Name:', 'name'),
                              ('Age:', 'age'),
                              ('Gender:', 'gender'),
                              ('City:', 'city'),
                              ('State:', 'state'),
                              ('Country:', 'country'),
                              ('Birth Date:', 'birth_date'),
                              ('E-mail:', 'email'),
                              ('WWW:', 'www'),
                              ('Occupation:', 'occupation'),
                              ('Phone Numbers:', 'phone_numbers'),
                              ('Languages:', 'languages'),
                              ('Description:', 'description'),
                             )

        genders = ('Male', 'Female')

        for header, key in profile_components:
            hbox = gtk.HBox()
            label = gtk.Label(header)
            label.set_size_request(130, -1)
            label.set_alignment(0, 0)

            value = self.user.get(key)
            if value == None:
                value = ''

            if key == 'gender':
                # create gender widget separately
                widget = gtk.combo_box_entry_new_text()
                for gender in genders:
                    widget.append_text(gender)
                entry = widget.child
                entry.set_text(str(value))

                widget.connect("changed", self.combo_changed, key)
            elif key == 'description':
                widget = gtk.TextView()
                widget.get_buffer().set_text(str(value))
                widget.set_property("wrap-mode", gtk.WRAP_CHAR)
                widget.set_size_request(-1, 100)
                entry = widget
            else:
                widget = gtk.Entry()
                widget.set_text(str(value))
                entry = widget

            entry.connect("focus-out-event", self.entry_focus_out, key)

            hbox.pack_start(label, False, False)
            hbox.pack_start(widget, True, True)

            self.profile_widgets[key] = entry
            user_info_vbox.pack_start(hbox, False, False)

        main_hbox.pack_start(left_hbox, False, False)
        main_hbox.pack_start(user_info_vbox, True, True)

        swindow.add_with_viewport(main_hbox)

        self.update_profile_widgets()

        self.pack_start(swindow, True, True)

    def image_clicked(self, widget, event):
        self.pic_dialog.set_picture(proximatestate.seek_face_name(self.user))
        self.pic_dialog.show()

    def got_picture(self, fname):
        self.community.set_my_face(fname)

    def combo_changed(self, widget, key):
        self.entry_focus_out(widget.child, None, key)

    def entry_focus_out(self, entry, event, key):
        if key == 'description':
            buf = entry.get_buffer()
            value = buf.get_text(buf.get_start_iter(), buf.get_end_iter())
        else:
            value = entry.get_text()
        if len(value) == 0:
            value = None
        if value != self.user.get(key):
            if self.user.set(key, value):
                self.community.announce_user_change(self.user, allowme=True)
            else:
                # re-insert old value if set fails
                value = self.user.get(key)
                if value == None:
                    value = ''
                entry.set_text(str(value))
Ejemplo n.º 5
0
class Community_Information_GUI:
    """The Class can be used to create new peer/personal communities."""
    
    def __init__(self, title, gui):
        self.main_gui = gui
        self.personal_community = False

        self.icon_fname = None
        self.icon_changed = False
        self.notification = get_plugin_by_type(PLUGIN_TYPE_NOTIFICATION)
        self.community = get_plugin_by_type(PLUGIN_TYPE_COMMUNITY)

        self.main_window = gui.get_main_window()

        new_title = title + ' Community'
        self.dialog = gtk.Dialog(new_title, self.main_window, \
                                 gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL, \
                                 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, \
                                  title, gtk.RESPONSE_OK))
        # this should be better for toplevel windows than set_size_request()
        self.dialog.set_default_size(400, 300)

        self.initialize_widgets()
        self.dialog.connect("response", self.response_handler)
        self.dialog.show_all()

        self.pic_dialog = Picture_Choose_Dialog(self.main_gui, self.got_picture)

    def response_handler(self, widget, event):
        if event == gtk.RESPONSE_OK:
            self.community_name = self.name_entry.get_text()
            if not valid_community(self.community_name):
                self.notification.ok_dialog('Error', 'Invalid community name.',
                    parent=self.dialog, modal=True)
                return True

            self.desc = self.description_tbuffer.get_text(self.description_tbuffer.get_start_iter(), self.description_tbuffer.get_end_iter())
            if self.desc == "<<Insert description>>":
                self.desc = None
                
            self.save_community_information(self.personal_community == False)

        self.pic_dialog.close()
        self.dialog.destroy()
        return True

    def save_community_information(self, peer=True):
        if peer:
            com = self.community.create_community(self.community_name, desc=self.desc)
            self.community.join_community(com)

            if self.icon_changed and not self.community.set_community_icon(com, self.icon_fname):
                self.notification.notify('Could not set community icon', True)
        else:
            # personal, public
            com = self.community.create_community(self.community_name, False, True, desc=self.desc)

            if self.icon_changed and not self.community.set_community_icon(com, self.icon_fname):
                self.notification.notify('Could not set community icon', True)
                
    def initialize_widgets(self):
        fwindow = new_scrollarea()
        viewport = gtk.Viewport()

        self.widgets_to_hide = []
        self.main_vbox = gtk.VBox()
        self.main_vbox.set_size_request(-1, 500)
        self.image_hbox = gtk.HBox()
        self.main_vbox.pack_start(self.image_hbox, False, False)

        # Community name, personal cbox, area size and image
        self.name_vbox = gtk.VBox()
        hbox = gtk.HBox()
        self.name_label = gtk.Label('Community\'s name:')
        hbox.pack_start(self.name_label, False, True)
        self.name_vbox.pack_start(hbox, False, True)
        self.name_entry = gtk.Entry()
        self.name_entry.set_size_request(-1, 32)
        self.name_vbox.pack_start(self.name_entry, False, True)

        hbox = gtk.HBox()
        self.personal_label = gtk.Label('Personal Community:')
        hbox.pack_start(self.personal_label, False, True)
        if self.community.personal_communities:
            self.name_vbox.pack_start(hbox, False, True)
        self.personal_cbutton = gtk.CheckButton()
        self.personal_cbutton.set_active(False)
        self.personal_cbutton.set_size_request(-1, 32)
        self.personal_cbutton.connect("clicked", self.checkbutton_clicked)
        hbox = gtk.HBox()
        hbox.pack_start(self.personal_cbutton, True, True)
        if self.community.personal_communities:
            self.name_vbox.pack_start(hbox, False, True)

        self.image_hbox.pack_start(self.name_vbox, False, True)
        self.image_eb = gtk.EventBox()
        self.image_eb.connect("button-press-event", self.image_clicked)
        self.image = gtk.Image()
        self.image.set_size_request(MAX_FACE_DIMENSION+10, MAX_FACE_DIMENSION+10)
        self.image.set_from_file(get_path(DEFAULT_COMMUNITY_ICON))
        self.image_eb.add(self.image)
        vbox = gtk.VBox()
        vbox.pack_start(self.image_eb, True, True)
        vbox.pack_start(gtk.Label('Click community\nicon to change it'), True, False)
        self.image_hbox.pack_end(vbox, False, False)
        
        hbox = gtk.HBox()
        desc_label = gtk.Label('Description: ')
        desc_label.set_size_request(-1, 32)
        hbox.pack_start(desc_label, False, True)
        self.main_vbox.pack_start(hbox, False, True)
        self.description_tview = gtk.TextView()
        self.description_tview.set_property("wrap-mode", gtk.WRAP_CHAR)
        self.description_tbuffer = gtk.TextBuffer()
        self.description_tbuffer.set_text("<<Insert description>>")
        self.description_tview.set_buffer(self.description_tbuffer)
        self.description_tview.set_size_request(300, 100)
        
        self.main_vbox.pack_start(self.description_tview, False, True)
        self.main_vbox.show_all()
        viewport.add(self.main_vbox)
        fwindow.add(viewport)
        self.dialog.vbox.pack_start(fwindow)

    def initialize_date_and_time_widgets(self):
        # community activation
        hbox = gtk.HBox()
        hbox.pack_start(gtk.Label('Activation Date & Time:'), False, True)
        self.widgets_to_hide.append(hbox)
        self.main_vbox.pack_start(hbox, False, True)

        hbox = gtk.HBox()
        self.start_date_entry = gtk.Entry()
        self.start_date_entry.set_size_request(-1, 32)
        self.start_date_button = gtk.Button("Date")
        self.start_date_button.set_size_request(80, -1)
        self.start_date_button.connect("clicked", self.sdate_clicked)
        hbox.pack_start(self.start_date_entry, False, True)
        hbox.pack_start(self.start_date_button, False, True)
        self.widgets_to_hide.append(hbox)
        self.main_vbox.pack_start(hbox, False, True)
        self.start_time_entry = gtk.Entry()
        self.start_time_entry.set_size_request(-1, 32)
        self.start_time_button = gtk.Button("Time")
        self.start_time_button.set_size_request(80, -1)
        self.start_time_button.connect("clicked", self.stime_clicked)
        hbox = gtk.HBox()
        hbox.pack_start(self.start_time_entry, False, True)
        hbox.pack_start(self.start_time_button, False, True)
        self.widgets_to_hide.append(hbox)
        self.main_vbox.pack_start(hbox, False, True)

        # community deactivation
        hbox = gtk.HBox()
        hbox.pack_start(gtk.Label('Deactivation Date & Time:'), False, True)
        self.widgets_to_hide.append(hbox)
        self.main_vbox.pack_start(hbox, False, True)

        hbox = gtk.HBox()
        self.end_date_entry = gtk.Entry()
        self.end_date_entry.set_size_request(-1, 32)
        self.end_date_button = gtk.Button("Date")
        self.end_date_button.set_size_request(80, -1)
        self.end_date_button.connect("clicked", self.sdate_clicked, False)
        hbox.pack_start(self.end_date_entry, False, True)
        hbox.pack_start(self.end_date_button, False, True)
        self.widgets_to_hide.append(hbox)
        self.main_vbox.pack_start(hbox, False, True)
        self.end_time_entry = gtk.Entry()
        self.end_time_entry.set_size_request(-1, 32)
        self.end_time_button = gtk.Button("Time")
        self.end_time_button.set_size_request(80, -1)
        self.end_time_button.connect("clicked", self.stime_clicked, False)
        hbox = gtk.HBox()
        hbox.pack_start(self.end_time_entry, False, True)
        hbox.pack_start(self.end_time_button, False, True)
        self.widgets_to_hide.append(hbox)
        self.main_vbox.pack_start(hbox, False, True)

    def checkbutton_clicked(self, widget):
        self.personal_community = self.personal_cbutton.get_active()

        if self.personal_community:
            for widget in self.widgets_to_hide:
                widget.hide_all()
        else:
            for widget in self.widgets_to_hide:
                widget.show_all()

    def image_clicked(self, widget, event=None):
        self.pic_dialog.set_picture(self.icon_fname)
        self.pic_dialog.show()

    def got_picture(self, fname):
        self.icon_fname = fname
        self.icon_changed = True
        if fname != None:
            self.image.set_from_file(fname)
        else:
            self.image.set_from_pixbuf(get_default_community_icon(self.com))

    def sdate_clicked(self, widget, start = True):
        fields = time.localtime()
        dialog = hildon.CalendarPopup(self.main_window, fields[0], fields[2], \
                                      fields[3])
        dialog.run()
        date = dialog.get_date()
        dialog.destroy()
        (year, month, day) = date
        if start:
            self.start_date_entry.set_text('%.4d-%.2d-%.2d' %(year, month, day))
        else:
            self.end_date_entry.set_text('%.4d-%.2d-%.2d' %(year, month, day))

    def stime_clicked(self, widget, start = True):
        time_picker = hildon.TimePicker(self.main_window)
        time_picker.run()
        selected_time = time_picker.get_time()
        time_picker.destroy()
        (hours, minutes) = selected_time

        str_hours = '%.2d' %(hours)
        str_mins = '%.2d' %(minutes)

        if start:
            self.start_time_entry.set_text('%s:%s' %(str_hours, str_mins))
        else:
            self.end_time_entry.set_text('%s:%s' %(str_hours, str_mins))
Ejemplo n.º 6
0
class Community_Page(GUI_Page):
    COL_ICON = 0
    COL_USER = 1
    COL_TITLE = 2
    COL_STATUS = 3

    def __init__(self, community_gui, gui, com):
        GUI_Page.__init__(self, com.get('name'))

        self.notification = get_plugin_by_type(PLUGIN_TYPE_NOTIFICATION)
        self.community = get_plugin_by_type(PLUGIN_TYPE_COMMUNITY)

        self.item_double_clicking = None
        self.community_gui = community_gui
        self.main_gui = gui
        self.com = com

        self.list_view = community_gui.list_view_setting.value

        self.profile_widgets = {}

        # model (icon, item, text)
        self.itemlist = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_PYOBJECT, str, str)
        self.update_members()

        self.pic_dialog = Picture_Choose_Dialog(gui, self.got_picture)

        self.notebook = gtk.Notebook()
        self.notebook.set_show_tabs(True)
        self.notebook.set_show_border(False)
        self.initialize_members_page()
        self.initialize_profile_page()
        self.initialize_modify_page()
        self.pack_start(self.notebook)

    def initialize_members_page(self):
        hbox = gtk.HBox()

        if self.list_view:
            # Display as a list
            self.itemview = gtk.TreeView(self.itemlist)
            self.itemview.connect('row-activated', self.handle_item_clicked)
            self.itemview.set_headers_visible(False)

            cr_icon = gtk.CellRendererPixbuf()
            cr_name = gtk.CellRendererText()
            cr_status = gtk.CellRendererText()

            column = gtk.TreeViewColumn('')
            column.pack_start(cr_icon, False)
            column.pack_start(cr_name)
            column.add_attribute(cr_icon, 'pixbuf', self.COL_ICON)
            column.add_attribute(cr_name, 'markup', self.COL_TITLE)
            self.itemview.append_column(column)

            column = gtk.TreeViewColumn('Status')
            column.pack_start(cr_status)
            column.add_attribute(cr_status, 'text', self.COL_STATUS)
            column.set_expand(True)
            self.itemview.append_column(column)
        else:
            # Icon display
            self.itemview = gtk.IconView(self.itemlist)
            self.itemview.set_spacing(6)
            self.itemview.set_row_spacing(9)
            self.itemview.connect('item-activated', self.handle_item_clicked)
            self.itemview.connect('button-press-event', self.view_clicked, None)
            self.itemview.set_pixbuf_column(self.COL_ICON)
            self.itemview.set_markup_column(self.COL_TITLE)

        swindow = new_scrollarea()
        swindow.add_with_viewport(self.itemview)

        hbox.pack_start(swindow)

        self.action_list = User_Action_List(self.community_gui, self.get_selected)
        hbox.pack_start(self.action_list.get_widget(), False, True)

        self.notebook.append_page(hbox, gtk.Label('Members'))

    def back_action(self):
        self.community_gui.com_pages.pop(self.com)
        self.main_gui.remove_page(self)
        self.destroy()
        return True

    def get_community(self):
        return self.com

    def update_community_page(self):
        self.update_profile_entries()
        self.update_profile_widgets()

    def update_members(self):
        users = self.community.get_community_members(self.com)
        myself = self.community.get_myself()
        # myself is not in active users list, so add separately here
        if self.com.get('peer') == True and \
           self.com in self.community.get_user_communities(myself):
            users.append(myself)

        for row in self.itemlist:
            user = row[self.COL_USER]
            if user not in users:
                self.itemlist.remove(row.iter)
            else:
                users.remove(user)

        # add new users to the end
        for user in users:
            icon = self.get_user_icon(user)
            title = self.get_user_display_name(user)
            if user == myself:
                self.itemlist.prepend([icon, user, title, user.get('status')])
            else:
                self.itemlist.append([icon, user, title, user.get('status')])

    def get_user_icon(self, user):
        icon = get_user_profile_picture(user)
        if self.list_view:
            return icon.scale_simple(48, 48, gtk.gdk.INTERP_BILINEAR)
        return icon

    def user_changes(self, user):
        self.update_members()
        self.update_profile_widgets()
        for row in self.itemlist:
            if user == row[self.COL_USER]:
                row[self.COL_ICON] = self.get_user_icon(user)
                row[self.COL_TITLE] = self.get_user_display_name(user)
                row[self.COL_STATUS] = user.get('status')
                break

    def get_user_display_name(self, user):
        nick = pango_escape(user.get('nick'))
        if user == self.community.get_myself():
            nick = '<b>%s</b> (me)' % nick
        return nick

    def handle_item_clicked(self, view, path, view_column=None):
        row = self.itemlist[path]
        user = row[self.COL_USER]
        self.community_gui.show_user_page(user)

    def view_clicked(self, iconview, event, param):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
            coords = event.get_coords()
            if coords == ():
                return
            (x,y) = coords

            # simulate double click with a timeout variable
            if not self.item_double_clicking:
                self.set_item_double_clicking(True)
                timeout_id = gobject.timeout_add(500, self.set_item_double_clicking, False)
                return

            path = iconview.get_path_at_pos(int(x), int(y))
            if path != None:
                # is the item already selected
                selected = iconview.path_is_selected(path)
                if selected:
                    self.handle_item_clicked(iconview, path)

    def set_item_double_clicking(self, doubleclick):
        self.item_double_clicking = doubleclick
        return False # timeout shouldn't call this again

    def get_selected(self):
        if self.list_view:
            model, selected = self.itemview.get_selection().get_selected_rows()
        else:
            selected = self.itemview.get_selected_items()
        if len(selected) > 0:
            path = selected[0] # there should be 0 or 1 selected items
            row = self.itemlist[path]
            value = row[self.COL_USER]
        else:
            value = self.com
        return value

    def initialize_profile_page(self):
        profile_hbox = gtk.HBox()
        vbox = gtk.VBox()

        myself = self.community.get_myself()
        is_member = (self.com in self.community.get_user_communities(myself))

        picture_vbox = gtk.VBox()
        self.profile_image = gtk.Image()
        self.profile_image.set_size_request(MAX_FACE_DIMENSION+10, MAX_FACE_DIMENSION+10)
        if is_member:
            eventbox = gtk.EventBox()
            eventbox.connect("button-press-event", self.image_clicked)
            eventbox.add(self.profile_image)
            picture_vbox.pack_start(gtk.Label('Click picture to change'))
            picture_vbox.pack_start(eventbox, True, True)
        else:
            picture_vbox.pack_start(self.profile_image, True, True)

        picture_hbox = gtk.HBox()
        picture_hbox.pack_start(picture_vbox, False, True)
        self.status_label = gtk.Label()
        self.status_label.set_line_wrap(True)
        picture_hbox.pack_start(self.status_label)
        vbox.pack_start(picture_hbox)

        self.profile_info_label = gtk.Label()
        self.profile_info_label.set_alignment(0.1, 0.01) # 0.01 on purpose
        self.profile_info_label.set_line_wrap(True)
        vbox.pack_start(self.profile_info_label)

        profile_hbox.pack_start(vbox)

        self.com_action_list = Community_Action_List(self.community_gui,
            self.get_community)
        profile_hbox.pack_start(self.com_action_list.action_view)

        swindow = new_scrollarea()
        swindow.set_border_width(0)
        swindow.add_with_viewport(profile_hbox)

        self.update_profile_widgets()

        self.notebook.append_page(swindow, gtk.Label('Profile'))

    def initialize_modify_page(self):
        vbox = gtk.VBox()

        # List of modifiable fields
        profile_components = [('Location: ', 'location'),
                              ('WWW: ', 'www'),
                              ('Description: ', 'description'),
                             ]

        for header, key in profile_components:
            hbox = gtk.HBox()
            label = gtk.Label(header)
            label.set_size_request(130, -1)
            label.set_alignment(0, 0)

            value = self.com.get(key)
            if value == None:
                value = ''

            if key == 'description':
                # create description widget separately
                entry = gtk.TextView()
                entry.get_buffer().set_text(str(value))
                entry.set_property("wrap-mode", gtk.WRAP_CHAR)
                entry.set_size_request(-1, 100)
            else:
                entry = gtk.Entry()
                entry.set_text(str(value))

            entry.connect("focus-out-event", self.entry_focus_out, key)

            hbox.pack_start(label, False)
            hbox.pack_start(entry)

            self.profile_widgets[key] = entry
            vbox.pack_start(hbox, False)

        self.locked_checkbox = gtk.CheckButton('Do not allow changes to the community icon from other users')
        vbox.pack_start(self.locked_checkbox, False, False)
        self.locked_checkbox.set_active(self.com.get('iconlocked'))
        self.locked_checkbox.connect('toggled', self.set_locked)

        myself = self.community.get_myself()
        if self.com in self.community.get_user_communities(myself):
            self.notebook.append_page(vbox, gtk.Label('Modify'))

        self.update_profile_entries()

    def set_locked(self, widget):
        self.com.set('iconlocked', widget.get_active())

    def update_profile_entries(self):
        for key, entry in self.profile_widgets.items():
            value = self.com.get(key)
            if value == None:
                value = ''

            if key == 'description':
                entry.get_buffer().set_text(str(value))
            else:
                entry.set_text(str(value))

    def update_profile_widgets(self):
        image = get_community_icon(self.com)
        self.profile_image.set_from_pixbuf(image)
        n = len(self.community.get_community_members(self.com))
        myself = self.community.get_myself()
        if self.com in self.community.get_user_communities(myself):
            n += 1
        status = '%d member' % n
        if n != 1:
            status += 's'
        self.status_label.set_text(status)
        self.profile_info_label.set_markup(self.construct_profile_info_str())

    def image_clicked(self, widget, event):
        self.pic_dialog.set_picture(seek_community_icon_name(self.com))
        self.pic_dialog.show()

    def got_picture(self, fname):
        myself = self.community.get_myself()
        if self.com in self.community.get_user_communities(myself):
            self.community.set_community_icon(self.com, fname)
            # increase profile version to indicate new community profile
            self.community.get_myself().update_attributes([])

    def construct_profile_info_str(self):

        def heading(s):
            # Returns a heading string s formatted with pango markup and
            # a new-line
            return '<span color="slategray" weight="bold" size="large">%s</span>\n' % pango_escape(s)

        def field(s):
            value = self.com.get(s)
            if value != None:
                return '%s: %s\n' % (field_descriptions[s], pango_escape(str(value)))
            else:
                return ''

        def join_list(l):
            out = []
            for s in l:
                value = self.com.get(s)
                if value != None:
                    out.append(pango_escape(str(value)))
            if len(out) > 0:
                return ', '.join(out) + '\n'
            else:
                return ''

        s = heading(self.com.get('name'))
        s += field('location')
        s += field('www')
        s += field('description')

        if get_debug_mode():
            s += heading('Debug information')
            s += field('v')
            s += field('iconversion')
            s += field('myiconversion')

        return s

    def entry_focus_out(self, entry, event, key):
        if key == 'description':
            buf = entry.get_buffer()
            value = buf.get_text(buf.get_start_iter(), buf.get_end_iter())
        else:
            value = entry.get_text()
        if value == '':
            value = None
        if value != self.com.get(key):
            if self.com.set(key, value):
                # increase profile version to indicate new community profile
                self.community.get_myself().update_attributes([])
            else:
                # re-insert old value if set fails
                value = self.com.get(key)
                if value == None:
                    value = ''
                entry.set_text(str(value))