예제 #1
0
class RadioBrowser(gtk.VBox):
    def __init__(self):
        gtk.VBox.__init__(self)

        # Init radiobar.
        self.__init_radiobar()

        # is loaded.
        self.homepage_load_flag = False
        self.home_page = HomePage()

        self.hot_page_view, self.hot_page_sw = self.get_radio_icon_view(
            TAG_HOT, 20)
        self.fast_page_view, self.fast_page_sw = self.get_radio_icon_view(
            TAG_FAST, 20)

        # Genres page
        self.genre_page = GenrePage()

        self.page_box = gtk.VBox()
        self.page_box.add(self.home_page)

        self.body_paned = HPaned(
            handle_color=app_theme.get_color("panedHandler"))
        self.body_paned.add1(self.radiobar)
        self.body_paned.add2(self.page_box)
        self.network_failed_box = NetworkConnectFailed(
            self.check_network_connection)
        self.check_network_connection(auto=True)

    def check_network_connection(self, auto=False):
        if is_network_connected():
            switch_tab(self, self.body_paned)
            if not auto:
                self.start_fetch_channels()
        else:
            switch_tab(self, self.network_failed_box)

    def __init_radiobar(self):
        self.radiobar = TreeView(enable_drag_drop=False,
                                 enable_multiple_select=False)
        items = []
        items.append(
            CategroyTreeItem(
                _("Home"), "home",
                lambda: switch_tab(self.page_box, self.home_page)))
        items.append(
            CategroyTreeItem(
                _("Hot MHz"), "hot",
                lambda: switch_tab(self.page_box, self.hot_page_sw)))
        items.append(
            CategroyTreeItem(
                _("Genres"), "genre",
                lambda: switch_tab(self.page_box, self.genre_page)))
        items.append(
            CategroyTreeItem(
                _("Pop MHz"), "up",
                lambda: switch_tab(self.page_box, self.fast_page_sw)))
        self.radiobar.add_items(items)
        self.radiobar.select_items([self.radiobar.visible_items[0]])
        self.radiobar.set_size_request(121, -1)
        self.radiobar.draw_mask = self.on_radiobar_draw_mask

    def on_radiobar_draw_mask(self, cr, x, y, w, h):
        draw_alpha_mask(cr, x, y, w, h, "layoutRight")

    def get_radio_icon_view(self, tag, limit=10, padding_x=0, padding_y=10):
        icon_view = RadioIconView(tag=tag,
                                  limit=limit,
                                  padding_x=padding_x,
                                  padding_y=padding_y)
        scrolled_window = icon_view.get_scrolled_window()
        return icon_view, scrolled_window

    def start_fetch_channels(self):
        self.fast_page_view.clear_items()
        self.hot_page_view.clear_items()
        self.home_page.start_fetch_channels()
        self.hot_page_view.start_fetch_channels()
        self.fast_page_view.start_fetch_channels()
        self.genre_page.start_fetch_channels()
class RadioBrowser(gtk.VBox):
    
    def __init__(self):
        gtk.VBox.__init__(self)
        
        # Init radiobar.
        self.__init_radiobar()
        
        # is loaded.
        self.homepage_load_flag = False
        self.home_page = HomePage()
        
        self.hot_page_view, self.hot_page_sw = self.get_radio_icon_view(TAG_HOT, 20)
        self.fast_page_view, self.fast_page_sw = self.get_radio_icon_view(TAG_FAST, 20)
        
        # Genres page
        self.genre_page = GenrePage()
        
        self.page_box = gtk.VBox()
        self.page_box.add(self.home_page)
        
        self.body_paned = HPaned(handle_color=app_theme.get_color("panedHandler"))
        self.body_paned.add1(self.radiobar)
        self.body_paned.add2(self.page_box)
        self.network_failed_box = NetworkConnectFailed(self.check_network_connection)
        self.check_network_connection(auto=True)
        
        
    def check_network_connection(self, auto=False):    
        if is_network_connected():
            switch_tab(self, self.body_paned)
            if not auto:
                self.start_fetch_channels()
        else:    
            switch_tab(self, self.network_failed_box)
            
    def __init_radiobar(self):    
        self.radiobar = TreeView(enable_drag_drop=False, enable_multiple_select=False)
        items = []
        items.append(CategroyTreeItem(_("Home"), "home",  lambda : switch_tab(self.page_box, self.home_page)))
        items.append(CategroyTreeItem(_("Hot MHz"), "hot", lambda : switch_tab(self.page_box, self.hot_page_sw)))
        items.append(CategroyTreeItem(_("Genres MHz"), "genre",  lambda : switch_tab(self.page_box, self.genre_page)))
        items.append(CategroyTreeItem(_("Pop MHz"), "up", lambda : switch_tab(self.page_box, self.fast_page_sw)))        
        self.radiobar.add_items(items)
        self.radiobar.select_items([self.radiobar.visible_items[0]])
        self.radiobar.set_size_request(121, -1)
        self.radiobar.draw_mask = self.on_radiobar_draw_mask        
        
    def on_radiobar_draw_mask(self, cr, x, y, w, h):    
        draw_alpha_mask(cr, x, y, w, h ,"layoutRight")
    
    def get_radio_icon_view(self, tag, limit=10, padding_x=0, padding_y=10):
        icon_view = RadioIconView(tag=tag, limit=limit, padding_x=padding_x, padding_y=padding_y)
        scrolled_window = icon_view.get_scrolled_window()
        return icon_view, scrolled_window
    
    def start_fetch_channels(self):
        self.fast_page_view.clear_items()
        self.hot_page_view.clear_items()
        self.home_page.start_fetch_channels()
        self.hot_page_view.start_fetch_channels()
        self.fast_page_view.start_fetch_channels()
        self.genre_page.start_fetch_channels()
예제 #3
0
class HomePage(gtk.HBox):
    '''
    class docs
    '''
    def __init__(self, data_manager, recommend_status):
        '''
        init docs
        '''
        # Init.
        gtk.HBox.__init__(self)
        self.data_manager = data_manager
        self.recommend_status = recommend_status

        self.background_box = BackgroundBox()
        self.background_box.draw_mask = self.draw_mask
        self.sidebar_box = gtk.VBox()
        self.page_box = gtk.VBox()
        self.sidebar_box.set_size_request(CATEGORY_VIEW_WIDTH, -1)

        self.canopy = gtk.VBox()
        self.canopy.set_size_request(-1, 19)

        self.search_align = gtk.Alignment()
        self.search_align.set(0.5, 0.5, 0, 0)
        self.search_align.set_padding(15, 5, 13, 13)
        self.search_align.add(search_entry)

        self.in_press = False
        self.press_return = False
        self.press_id = 0
        self.show_timeout_id = None
        self.entry_changed = False

        search_entry.entry.connect("changed", self.search_entry_changed)
        search_entry.entry.connect("key-press-event",
                                   self.search_entry_key_press)
        search_entry.entry.connect("key-release-event",
                                   self.search_entry_key_release)
        search_entry.connect(
            "action-active",
            lambda entry, search_string: self.show_search_page(search_string))
        search_entry.entry.connect(
            "press-return",
            lambda entry: self.show_search_page(entry.get_text(), True))

        self.recommend_item = RecommendItem(data_manager,
                                            self.recommend_status)

        category_items = []
        for (index, first_category_name) in enumerate(
                data_manager.get_first_category()):
            category_items.append(
                CategoryItem(index + 1, first_category_name, data_manager))

        self.category_view = TreeView(
            [self.recommend_item] + category_items,
            enable_drag_drop=False,
            enable_multiple_select=False,
            expand_column=0,
        )
        self.category_view.draw_mask = self.draw_mask
        self.category_view.set_size_request(-1, 470)

        self.category_view_align = gtk.Alignment()
        self.category_view_align.set(0.5, 0.5, 1, 1)
        self.category_view_align.set_padding(10, 10, 0, 0)
        self.category_view_align.add(self.category_view)

        self.background_box.pack_start(self.canopy, False, False)
        self.background_box.pack_start(self.search_align, True, True)
        self.background_box.pack_end(self.category_view_align, False, False)
        self.sidebar_box.pack_start(self.background_box, False, False)

        self.split_line = gtk.VBox()
        self.split_line.set_size_request(1, -1)

        self.pack_start(self.sidebar_box, False, False)
        self.pack_start(self.split_line, False, False)
        self.pack_start(self.page_box, True, True)

        self.canopy.connect("expose-event", self.expose_canopy)
        self.split_line.connect("expose-event", self.expose_split_line)

        global_event.register_event("show-pkg-view", self.show_pkg_view)
        global_event.register_event("category-expand",
                                    self.category_expand_handler)

    def category_expand_handler(self, item):
        self.category_view.visible_item(item.child_items[-1])

    def jump_to_category(self, first_category_name, second_category_name):

        for item in self.category_view.visible_items:
            if isinstance(item, CategoryItem) and item.is_expand:
                item.unexpand()

        for item in self.category_view.visible_items:
            if isinstance(
                    item, CategoryItem
            ) and item.first_category_name == first_category_name:
                item.expand()
                break

        for item in self.category_view.visible_items:
            if isinstance(
                    item, SecondCategoryItem
            ) and item.second_category_name == second_category_name:
                self.category_view.select_items([item])
                self.category_view.visible_item(item)
                item.button_press(0, 0, 0)
                break

    def draw_mask(self, cr, x, y, w, h):
        '''
        Draw mask interface.

        @param cr: Cairo context.
        @param x: X coordiante of draw area.
        @param y: Y coordiante of draw area.
        @param w: Width of draw area.
        @param h: Height of draw area.
        '''
        sidebar_color = app_theme.get_color("sidebar_background").get_color()
        draw_vlinear(cr, x, y, w, h, [
            (0, (sidebar_color, 0.9)),
            (1, (sidebar_color, 0.9)),
        ])

    def expose_canopy(self, widget, event):
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation
        canopy_color = app_theme.get_color("sidebar_select").get_color()

        canopy_img_blue_path = os.path.join(get_parent_dir(__file__,
                                                           2), "image",
                                            "canopy", "canopy-blue.png")
        canopy_img_yellow_path = os.path.join(get_parent_dir(__file__,
                                                             2), "image",
                                              "canopy", "canopy-yellow.png")

        draw_pixbuf(cr, gtk.gdk.pixbuf_new_from_file(canopy_img_yellow_path),
                    rect.x, rect.y)

        surface = cairo.ImageSurface.create_from_png(canopy_img_blue_path)
        cr.set_source_rgb(*color_hex_to_cairo(canopy_color))
        cr.mask_surface(surface, rect.x, rect.y)

    def expose_split_line(self, widget, event):
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation

        cr.set_source_rgb(*color_hex_to_cairo("#e5e5e5"))
        cr.rectangle(rect.x, rect.y, 1, rect.height)
        cr.fill()

        return True

    def search_entry_changed(self, entry, entry_string):
        self.press_id += 1
        self.press_return = False
        self.entry_changed = True

    def search_entry_key_press(self, widget, event):
        self.in_press = True
        self.press_id += 1

        remove_timeout_id(self.show_timeout_id)

    def search_entry_key_release(self, widget, event):
        self.in_press = False
        press_id = copy.deepcopy(self.press_id)
        remove_timeout_id(self.show_timeout_id)
        self.show_timeout_id = gobject.timeout_add(
            200, lambda: self.popup_completion(press_id))

    def popup_completion(self, press_id):
        if (not self.in_press) and (
                not self.press_return
        ) and press_id == self.press_id and self.entry_changed:
            search_string = search_entry.get_text()
            if len(search_string.strip()) >= 3:
                match_pkgs = self.data_manager.get_pkgs_match_input(
                    search_string)
                if len(match_pkgs) > 0:
                    completion_window.show(search_string, match_pkgs)
                else:
                    completion_grab_window.popup_grab_window_focus_out()
            else:
                completion_grab_window.popup_grab_window_focus_out()

            self.entry_changed = False

    def show_search_page(self, search_string, press_return=False):
        if search_string.strip() != "":
            self.category_view.unselect_all()

            self.press_return = press_return

            if self.press_return:
                completion_grab_window.popup_grab_window_focus_out()

            search_page = SearchPage(self.data_manager)
            self.show_pkg_view(search_page)
            search_page.update(
                map(lambda word: word.encode("utf8"),
                    search_string.split(" ")))
        else:
            global_logger.warn("empty string in search text input")

    def show_pkg_view(self, widget):
        container_remove_all(self.page_box)
        self.page_box.pack_start(widget, True, True)

        self.page_box.show_all()
class Region(gtk.Alignment):
    def __init__(self, connection=None):
        gtk.Alignment.__init__(self, 0, 0, 0, 0)

        #################
        self.provider_select = None
        self.connect('expose-event', self.expose_event)
        self.prop_dict = {}

        main_table = gtk.Table(2, 2, False)
        main_table.set_row_spacing(1, 10)
        main_table.set_col_spacings(4)
        self.add(main_table)

        self.country_tree = TreeView(
            enable_multiple_select=False,
            enable_drag_drop=False,
        )
        self.country_tree.set_expand_column(1)

        self.country_tree.set_size_request(365, 380)
        self.country_tree.draw_mask = self.draw_mask
        self.country_tree.connect("button-press-item", self.country_selected)
        left_box_align = gtk.Alignment(0, 0, 0, 0)
        left_box_align.set_padding(1, 1, 1, 1)
        left_box_align.add(self.country_tree)
        left_box_align.show_all()

        left_box = gtk.VBox()
        # wrap title
        country_title = TitleBar(
            app_theme.get_pixbuf("network/globe-green.png"),
            _("Country or Region:"),
            has_separator=False)
        left_box.pack_start(country_title, False, False)
        left_box.pack_start(left_box_align, False, False)

        self.provider_tree = TreeView(
            enable_multiple_select=False,
            enable_drag_drop=False,
        )
        self.provider_tree.set_expand_column(0)
        self.provider_tree.set_size_request(365, 380)
        self.provider_tree.draw_mask = self.draw_mask
        self.provider_tree.connect("button-press-item", self.provider_selected)
        right_box_align = gtk.Alignment(0, 0, 0, 0)
        right_box_align.set_padding(1, 1, 1, 1)
        right_box_align.add(self.provider_tree)
        right_box = gtk.VBox()
        # wrap title
        provider_title = TitleBar(app_theme.get_pixbuf("network/building.png"),
                                  _("Provider:"),
                                  has_separator=False)
        right_box.pack_start(provider_title, False, False)
        right_box.pack_start(right_box_align, False, False)

        main_left_align = gtk.Alignment(0, 0, 0, 0)
        main_left_align.set_padding(15, 0, 20, 0)
        main_left_align.add(left_box)
        main_table.attach(main_left_align, 0, 1, 0, 1)
        main_right_align = gtk.Alignment(0, 0, 0, 0)
        main_right_align.set_padding(15, 0, 0, 20)
        main_right_align.add(right_box)
        main_table.attach(main_right_align, 1, 2, 0, 1)

        hints = _(
            "Tips:This assistant helps you easily set up a mobile broadband connection to a cellular network."
        )

        left_box_align.connect("expose-event", self.expose_outline)
        right_box_align.connect("expose-event", self.expose_outline)

        next_button = Button("Next")
        next_button.connect("clicked", self.next_button_clicked)

        self.foot_box = FootBox()
        self.foot_box.set_buttons([next_button])
        self.foot_box.set_tip(hints)
        main_table.attach(self.foot_box, 0, 2, 1, 2)

        self.show_all()
        #self.init()

    def expose_outline(self, widget, event):
        cr = widget.window.cairo_create()
        rect = widget.allocation
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            cr.set_source_rgb(*BORDER_COLOR)
            cr.rectangle(rect.x, rect.y, rect.width, rect.height)
            cr.stroke()

    def draw_mask(self, cr, x, y, w, h):
        cr.set_source_rgb(1, 1, 1)
        cr.rectangle(x, y, w, h)
        cr.fill()

    def expose_event(self, widget, event):
        cr = widget.window.cairo_create()
        rect = widget.allocation
        cr.set_source_rgb(1, 1, 1)
        cr.rectangle(rect.x, rect.y, rect.width, rect.height)
        cr.fill()

    def expose_hint_background(self, widget, event):
        bg_color = color_hex_to_cairo(TREEVIEW_BG_COLOR)
        cr = widget.window.cairo_create()
        rect = widget.allocation
        cr.set_source_rgb(*bg_color)
        cr.rectangle(rect.x, rect.y, rect.width, rect.height)
        cr.fill()
        with cairo_disable_antialias(cr):
            cr.set_source_rgb(*BORDER_COLOR)
            cr.set_line_width(1)
            cr.rectangle(rect.x, rect.y, rect.width, rect.height - 1)
            cr.stroke()

    def next_button_clicked(self, widget):
        # 检查是否选择了运营商
        if not self.provider_select:
            print "provider has not selected"
            return
        try:
            self.plan_select
        except:
            self.plan_select = None

        def add_keys(settings):
            self.prop_dict = settings

        username = self.__sp.get_provider_username(self.code,
                                                   self.provider_select)
        password = self.__sp.get_provider_password(self.code,
                                                   self.provider_select)
        add_keys({
            "cdma": {
                "number": "#777",
                "username": username,
                "password": password
            }
        })
        provider_type = "cdma"
        if self.plan_select:
            self.prop_dict.pop("cdma")
            apn = self.plan_select
            index = self.__sp.get_provider_apns_name(
                self.code, self.provider_select).index(apn)
            (network_id, network_type) = self.__sp.get_provider_networks(
                self.code, self.provider_select)[index]
            add_keys({
                "gsm": {
                    "number": "*99#",
                    "username": username,
                    "password": password,
                    "apn": apn,
                    #"network_id": network_id,
                    "network_type": network_type
                }
            })
            provider_type = "gsm"

        #setting_page = nm_module.slider.get_page_by_name("setting")
        #broadband = setting_page.setting_group.get_broadband()
        if self.connection_type == None:
            new_connection = getattr(nm_module.nm_remote_settings,
                                     "new_%s_connection" % provider_type)()
            Dispatcher.emit("region-back", new_connection, self.prop_dict,
                            provider_type)

            #setting_page.sidebar.new_connection_list[provider_type].append(new_connection)
            #setting_page.init(setting_page.sidebar.new_connection_list)
            #setting_page.sidebar.set_active(new_connection)
            #broadband.set_new_values(self.prop_dict, provider_type)
        else:
            Dispatcher.emit("region-back", self.connection, self.prop_dict,
                            provider_type)

            #broadband.set_new_values(self.prop_dict, provider_type)

        nm_module.slider._slide_to_page("setting", "none")

    def init(self, connection):
        if connection == None:
            self.connection_type = None
        else:
            self.connection = connection
            mobile_type = connection.get_setting("connection").type
            self.connection_type = mobile_type
        Dispatcher.send_submodule_crumb(_("Region"), 2)

        from mm.provider import ServiceProviders
        self.__sp = ServiceProviders()
        self.country_list = self.__sp.get_country_name_list()
        self.country_tree.delete_all_items()
        self.country_tree.add_items(
            [CountryItem(_(country)) for country in self.country_list])
        # add a bottom line for last item

        code = self.__sp.get_country_from_timezone()

        self.country_codes = self.__sp.get_country_list()
        try:
            selected_country = self.country_tree.visible_items[
                self.country_codes.index(code)]
            self.country_tree.select_items([selected_country])
            self.auto_scroll_to()
            self.country_tree.emit("button-press-item", selected_country, 0, 1,
                                   1)
        except:
            pass

    def country_selected(self, widget, w, a, b, c):
        self.provider_tree.delete_all_items()
        self.code = self.country_codes[widget.select_rows[0]]
        if self.connection_type:
            self.provider_names = getattr(
                self.__sp, "get_country_%s_providers_name" %
                self.connection_type)(self.code)
        else:
            self.provider_names = self.__sp.get_country_providers_name(
                self.code)

        self.provider_select = None
        self.provider_tree.add_items(
            [Item(p, self.__sp, self.code) for p in self.provider_names])
        self.provider_tree.show_all()

    def provider_selected(self, widget, item, column, offset_x, offset_y):
        if type(item) is Item:
            self.provider_select = item.content
            self.plan_select = None
        else:
            self.plan_select = item.content

    def auto_scroll_to(self):
        vadjust = self.country_tree.scrolled_window.get_vadjustment()
        upper = vadjust.upper
        page_size = vadjust.page_size

        vadjust.set_value(
            min(upper - page_size,
                (self.country_tree.select_rows[0] - 4) * 30))
class PreferenceDialog(DialogBox):
    
    def __init__(self):
        super(PreferenceDialog, self).__init__(_("Preferences"), 575, 495, 
                                               mask_type=DIALOG_MASK_MULTIPLE_PAGE,
                                               close_callback=self.hide_all)
        
        self.set_position(gtk.WIN_POS_CENTER)
        
        self.main_box = gtk.VBox()
        close_button = Button(_("Close"))
        close_button.connect("clicked", lambda w: self.hide_all())
        
        # Init widget.
        self.general_setting = GeneralSetting()
        self.hotkey_setting = HotKeySetting()
        self.desktop_lyrics_setting = DesktopLyricsSetting()
        self.scroll_lyrics_setting = ScrollLyricsSetting()
        self.plugins_manager = PluginsManager()
        
        # Category bar
        self.category_bar = TreeView(enable_drag_drop=False, enable_multiple_select=False)
        self.category_bar.set_expand_column(0)
        self.category_bar.draw_mask = self.draw_treeview_mask
        self.category_bar.set_size_request(132, 516)
        self.category_bar.connect("single-click-item", self.on_categorybar_single_click)

        # Init catagory bar.
        self.__init_category_bar()
        
        category_box = gtk.VBox()
        background_box = BackgroundBox()
        background_box.set_size_request(132, 11)
        background_box.draw_mask = self.draw_treeview_mask
        category_box.pack_start(background_box, False, False)
        
        category_bar_align = gtk.Alignment()
        category_bar_align.set(0, 0, 1, 1,)
        category_bar_align.set_padding(0, 1, 0, 0)
        category_bar_align.add(self.category_bar)
        category_box.pack_start(category_bar_align, True, True)
        
        # Pack widget.
        left_box = gtk.VBox()
        self.right_box = gtk.VBox()
        left_box.add(category_box)
        self.right_box.add(self.general_setting)
        right_align = gtk.Alignment()
        right_align.set_padding(0, 0, 10, 0)
        right_align.add(self.right_box)

        body_box = gtk.HBox()
        body_box.pack_start(left_box, False, False)
        body_box.pack_start(right_align, False, False)
        self.main_box.add(body_box)
        
        # DialogBox code.
        self.body_box.pack_start(self.main_box, True, True)
        self.right_button_box.set_buttons([close_button])        
        
    def __init_category_bar(self):    
        general_normal_item = NormalItem(_("General"), self.general_setting)
        hotkey_normal_item = NormalItem(_("Hotkeys"), self.hotkey_setting)
        self.lyrics_expand_item = ExpandItem(_("Lyrics"), None)
        self.lyrics_expand_item.add_childs([(_("Desktop"), self.desktop_lyrics_setting),
                                       (_("Window"), self.scroll_lyrics_setting)])
        self.plugins_expand_item = NormalItem(_("Plugins"), self.plugins_manager)
        about_normal_item = NormalItem(_("About"), AboutBox())
        
        items = [general_normal_item,
                 hotkey_normal_item,
                 self.lyrics_expand_item,
                 self.plugins_expand_item,
                 about_normal_item]
        self.category_bar.add_items(items)
        self.category_bar.select_items([general_normal_item])
        
    def switch_lyrics_page(self, index=3):
        self.lyrics_expand_item.try_to_expand()
        show_item = self.category_bar.visible_items[index]
        self.category_bar.select_items([show_item])
        self.on_categorybar_single_click(self.category_bar, show_item, None, None, None)
        
    def show_scroll_lyrics_page(self):
        self.switch_lyrics_page(4)
        self.show_all()
        
    def show_desktop_lyrics_page(self):    
        self.switch_lyrics_page(3)
        self.show_all()
    
    def draw_treeview_mask(self, cr, x, y, width, height):
        draw_alpha_mask(cr, x, y, width, height, ("#FFFFFF", 0.9))
    
    def on_categorybar_single_click(self, widget, item, column, x, y):
        if item.allocate_widget:
            switch_tab(self.right_box, item.allocate_widget)

    def load_plugins(self):        
        self.plugins_manager.flush_plugins()
class WebcastsBrowser(gtk.VBox, SignalContainer):
    
    def __init__(self):
        gtk.VBox.__init__(self)
        SignalContainer.__init__(self)

        # Init categorys.
        self.get_categorys()
        
        # load data.
        self.__load_webcast_query()
        
        # Init webcastbar.
        self.__init_webcastbar()
        
        # Init iconview.
        self.metro_view = self.get_icon_view()
        self.metro_view_sw = self.metro_view.get_scrolled_window()
        
        self.page_box = gtk.VBox()
        self.page_box.add(self.metro_view_sw)
        
        
        # webcasts view
        self.webcast_view = self.get_webcast_view()
        self.webcast_view_sw = self.webcast_view.get_scrolled_window()
        
        # collect view
        self.collected_db_file = get_config_file("favorite_webcasts.db")
        self.collected_view = self.get_webcast_view()
        self.collected_view_sw = self.collected_view.get_scrolled_window()
        
        # Init collect view.
        
        # init listview page.
        self.init_listview_page()
        Dispatcher.connect("change-webcast", self.on_dispatcher_change_webcast)
        WebcastDB.connect("changed", self.on_db_update_songs)
        
        body_paned = HPaned(handle_color=app_theme.get_color("panedHandler"), enable_drag=True)
        body_paned.add1(self.webcastbar)
        body_paned.add2(self.page_box)
        self.add(body_paned)
        
    def get_categorys(self):    
        lang = utils.get_system_lang()
        if lang.startswith("zh"):
            self.__categorys = ["region", "genre", "composite"]
            self.current_category = "region"            
        else:    
            self.__categorys = ["region_en", "genre_en"]
            self.current_category = "region_en"            
            
        self.__category_gettexts = {
            "region" : "地域分类",
            "genre"  : "流派分类",
            "region_en" : _("Region"),
            "genre_en"  : _("Genre"),
            "composite"  : "综合分类",
            "finance" : "财经",
            "sports"  : "体育",
            "music"   : "音乐",
            "news"    : "新闻",
            "network" : "网络",
            }    
        
    def __load_webcast_query(self):    
        self.__db_query = WebcastQuery()        
        if WebcastDB.isloaded():
            self.__on_db_loaded()
        else:    
            WebcastDB.connect("loaded", lambda obj: self.__on_db_loaded())
            
    def __on_db_loaded(self):        
        self.autoconnect(self.__db_query, "added", self.__on_added_songs)
        self.autoconnect(self.__db_query, "removed", self.__on_removed_songs)
        self.autoconnect(self.__db_query, "update-songs", self.__on_update_songs)
        self.autoconnect(self.__db_query, "full-update", self.__on_full_update)
        self.__db_query.set_query()
        
    def __on_added_songs(self, db_query, songs):    
        self.reload_flag = True
    
    def __on_removed_songs(self, db_query, songs):
        self.reload_flag = True
    
    def __on_update_songs(self, db_query, songs):
        self.reload_flag = True
    
    def __on_full_update(self, db_query):
        self.load_view_data()
        self.load_collect_data()
        
    def __init_webcastbar(self):    
        self.webcastbar = TreeView(enable_drag_drop=False, enable_multiple_select=False)
        self.webcastbar.connect("single-click-item", self.on_webcastbar_single_click_item)
        items = []
        for category in self.__categorys:
            items.append(CategoryTreeItem(self.__category_gettexts[category], category=category))
        items.append(CollectTreeItem(_("Favorites")))    
        self.webcastbar.add_items(items)
        self.webcastbar.select_items([self.webcastbar.visible_items[0]])
        self.webcastbar.set_size_request(121, -1)
        self.webcastbar.draw_mask = self.on_webcastbar_draw_mask        
        
    def on_webcastbar_draw_mask(self, cr, x, y, w, h):    
        draw_alpha_mask(cr, x, y, w, h ,"layoutRight")
        
    def on_webcastbar_single_click_item(self, widget, item, column, x, y):    
        if hasattr(item, "collect_flag"):
            switch_tab(self.page_box, self.collected_view_sw)
        else:    
            widget = self.page_box.get_children()[0]
            if widget != self.metro_view_sw:
                switch_tab(self.page_box, self.metro_view_sw)            
            
            if self.current_category != item.category:
                self.current_category = item.category
                self.load_view_data()
        
    def init_listview_page(self):    
        self.listview_page = gtk.VBox()
        self.text_prompt = TextPrompt("Default")
        prompt_align = set_widget_gravity(self.text_prompt, 
                                          paddings=(10, 10, 0, 0))
        prompt_box = gtk.HBox()
        back_button = BackButton()
        back_button.connect("clicked", self.on_backbutton_clicked)
        back_button_align = set_widget_gravity(back_button, gravity=(0.5, 0.5, 0, 0),
                                               paddings=(0, 0, 10, 5))
        prompt_box.pack_start(back_button_align, False, True)
        prompt_box.pack_start(prompt_align, False, False)
        
        self.listview_page.pack_start(prompt_box, False, True)
        self.listview_page.pack_start(self.webcast_view_sw, True, True)
        
    def on_backbutton_clicked(self, widget):    
        switch_tab(self.page_box, self.metro_view_sw)
        
    def switch_to_listview(self, category, title):    
        self.text_prompt.set_text(title)
        self.webcast_view.clear()
        
        songs = self.__db_query.get_songs(category, title)
        self.webcast_view.add_webcasts(songs)
        switch_tab(self.page_box, self.listview_page)
        
        
    def load_view_data(self):    
        self.metro_view.clear()                    
        if self.current_category == "composite":
            child_datas = self.__db_query.get_composite_categorys()
            gettext_datas = []
            for child in child_datas:
                gettext_datas.append((self.__category_gettexts[child], child))
            self.metro_view.add_composite_items(gettext_datas)    
                
        else:    
            child_datas = self.__db_query.get_info(self.current_category)[0]
            child_datas.sort(key=lambda x: locale.strxfrm(x))
            self.metro_view.add_webcast_items(child_datas)            
            
    def load_collect_data(self):        
        try:
            collected_objs = utils.load_db(self.collected_db_file)
        except:    
            collected_objs = None

        if collected_objs:    
            songs = [ WebcastDB.get_song(uri) for uri in collected_objs]
        else:    
            songs = None
            
        if songs:
            songs = [ song for song in songs if song.get("collected", False)]            
            if songs:
                self.collected_view.add_webcasts(songs)
        
    def get_icon_view(self):
        icon_view = WebcastIconView()
        icon_view.connect("single-click-item", self.on_iconview_single_click_item)
        icon_view.connect("double-click-item", self.on_iconview_single_click_item)
        return icon_view
    
    
    def on_iconview_single_click_item(self, widget, item, x, y):
        if item.is_composited:
            category = item.category
        else:    
            category = self.current_category
            
        title = item.title
        if item.is_composited:
            self.switch_to_listview(category, title)
        else:    
            self.switch_to_listview(category, title)
        
    def get_webcast_view(self):    
        webcast_view = MultiDragWebcastView()
        webcast_view.keymap.update({"BackSpace" : lambda : self.on_backbutton_clicked(None)})        
        return webcast_view

    
    def on_dispatcher_change_webcast(self, widget, song):
        item = self.collected_view.get_webcast_item(song)
        if item and not song.get("collected", False):
            self.collected_view.delete_items([item])
        elif song.get("collected", False):    
            self.collected_view.add_webcasts([song])
        
    
    def on_db_update_songs(self, db, infos):
        for song, tags, new_tags in infos:
            if new_tags.has_key("collected"):
                item = self.collected_view.get_webcast_item(song)
                if item:
                    if not new_tags.get("collected", False):
                        self.collected_view.delete_items([item])
                else:    
                    if new_tags.get("collected", False):
                        self.collected_view.add_webcasts([song])
        
    def save(self):
        songs = self.collected_view.get_webcasts()
        uris = [ song.get("uri") for song in songs if song.get("uri")]
        utils.save_db(uris, self.collected_db_file)
class HomePage(gtk.HBox):
    '''
    class docs
    '''
	
    def __init__(self, data_manager, recommend_status):
        '''
        init docs
        '''
        # Init.
        gtk.HBox.__init__(self)
        self.data_manager = data_manager
        self.recommend_status = recommend_status
        
        self.background_box = BackgroundBox()
        self.background_box.draw_mask = self.draw_mask
        self.sidebar_box = gtk.VBox()
        self.page_box = gtk.VBox()
        self.sidebar_box.set_size_request(CATEGORY_VIEW_WIDTH, -1)
        
        self.canopy = gtk.VBox()
        self.canopy.set_size_request(-1, 19)
        
        self.search_align = gtk.Alignment()
        self.search_align.set(0.5, 0.5, 0, 0)
        self.search_align.set_padding(15, 5, 13, 13)
        self.search_align.add(search_entry)
        
        self.in_press = False
        self.press_return = False
        self.press_id = 0
        self.show_timeout_id = None
        self.entry_changed = False
        
        search_entry.entry.connect("changed", self.search_entry_changed)
        search_entry.entry.connect("key-press-event", self.search_entry_key_press)
        search_entry.entry.connect("key-release-event", self.search_entry_key_release)
        search_entry.connect("action-active", lambda entry, search_string: self.show_search_page(search_string))
        search_entry.entry.connect("press-return", lambda entry: self.show_search_page(entry.get_text(), True))
        
        self.recommend_item = RecommendItem(data_manager, self.recommend_status)
       
        category_items = []
        for (index, first_category_name) in enumerate(data_manager.get_first_category()):
            category_items.append(CategoryItem(index+1, first_category_name, data_manager))
        
        self.category_view = TreeView(
            [self.recommend_item] + category_items,
            enable_drag_drop=False,
            enable_multiple_select=False,
            expand_column=0,
            )
        self.category_view.draw_mask = self.draw_mask
        self.category_view.set_size_request(-1, 470)

        self.category_view_align = gtk.Alignment()
        self.category_view_align.set(0.5, 0.5, 1, 1)
        self.category_view_align.set_padding(10, 10, 0, 0)
        self.category_view_align.add(self.category_view)
        
        self.background_box.pack_start(self.canopy, False, False)
        self.background_box.pack_start(self.search_align, True, True)
        self.background_box.pack_end(self.category_view_align, False, False)
        self.sidebar_box.pack_start(self.background_box, False, False)
        
        self.split_line = gtk.VBox()
        self.split_line.set_size_request(1, -1)
        
        self.pack_start(self.sidebar_box, False, False)
        self.pack_start(self.split_line, False, False)
        self.pack_start(self.page_box, True, True)
        
        self.canopy.connect("expose-event", self.expose_canopy)
        self.split_line.connect("expose-event", self.expose_split_line)
        
        global_event.register_event("show-pkg-view", self.show_pkg_view)
        global_event.register_event("category-expand", self.category_expand_handler)

    def category_expand_handler(self, item):
        self.category_view.visible_item(item.child_items[-1])
        
    def jump_to_category(self, first_category_name, second_category_name):
        
        for item in self.category_view.visible_items:
            if isinstance(item, CategoryItem) and item.is_expand:
                item.unexpand()
        
        for item in self.category_view.visible_items:
            if isinstance(item, CategoryItem) and item.first_category_name == first_category_name:
                item.expand()
                break

        for item in self.category_view.visible_items:
            if isinstance(item, SecondCategoryItem) and item.second_category_name == second_category_name:
                self.category_view.select_items([item])
                self.category_view.visible_item(item)
                item.button_press(0, 0, 0)
                break
        
    def draw_mask(self, cr, x, y, w, h):
        '''
        Draw mask interface.
        
        @param cr: Cairo context.
        @param x: X coordiante of draw area.
        @param y: Y coordiante of draw area.
        @param w: Width of draw area.
        @param h: Height of draw area.
        '''
        sidebar_color = app_theme.get_color("sidebar_background").get_color()
        draw_vlinear(cr, x, y, w, h,
                     [(0, (sidebar_color, 0.9)),
                      (1, (sidebar_color, 0.9)),]
                     )
        
    def expose_canopy(self, widget, event):
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation
        canopy_color = app_theme.get_color("sidebar_select").get_color()
        
        canopy_img_blue_path = os.path.join(get_parent_dir(__file__, 2), "image", "canopy", "canopy-blue.png")
        canopy_img_yellow_path = os.path.join(get_parent_dir(__file__, 2), "image", "canopy", "canopy-yellow.png")

        draw_pixbuf(
            cr,
            gtk.gdk.pixbuf_new_from_file(canopy_img_yellow_path),
            rect.x,
            rect.y)
        
        surface = cairo.ImageSurface.create_from_png(canopy_img_blue_path)
        cr.set_source_rgb(*color_hex_to_cairo(canopy_color))
        cr.mask_surface(surface, rect.x, rect.y)

    def expose_split_line(self, widget, event):
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation

        cr.set_source_rgb(*color_hex_to_cairo("#e5e5e5"))
        cr.rectangle(rect.x, rect.y, 1, rect.height)
        cr.fill()
        
        return True
        
    def search_entry_changed(self, entry, entry_string):
        self.press_id += 1
        self.press_return = False
        self.entry_changed = True
        
    def search_entry_key_press(self, widget, event):
        self.in_press = True
        self.press_id += 1
        
        remove_timeout_id(self.show_timeout_id)
        
    def search_entry_key_release(self, widget, event):
        self.in_press = False
        press_id = copy.deepcopy(self.press_id)
        remove_timeout_id(self.show_timeout_id)
        self.show_timeout_id = gobject.timeout_add(200, lambda : self.popup_completion(press_id))
        
    def popup_completion(self, press_id):
        if (not self.in_press) and (not self.press_return) and press_id == self.press_id and self.entry_changed:
            search_string = search_entry.get_text()
            if len(search_string.strip()) >= 3:
                match_pkgs = self.data_manager.get_pkgs_match_input(search_string)
                if len(match_pkgs) > 0:
                    completion_window.show(search_string, match_pkgs)
                else:
                    completion_grab_window.popup_grab_window_focus_out()
            else:
                completion_grab_window.popup_grab_window_focus_out()
                
            self.entry_changed = False
        
    def show_search_page(self, search_string, press_return=False):
        if search_string.strip() != "":
            self.category_view.unselect_all()
            
            self.press_return = press_return
            
            if self.press_return:
                completion_grab_window.popup_grab_window_focus_out()
            
            search_page = SearchPage(self.data_manager)
            self.show_pkg_view(search_page)
            search_page.update(map(lambda word: word.encode("utf8"), search_string.split(" ")))
        else:
            logger.warning("empty string in search text input")
        
    def show_pkg_view(self, widget):
        container_remove_all(self.page_box)
        self.page_box.pack_start(widget, True, True)
        
        self.page_box.show_all()
class WebcastsBrowser(gtk.VBox, SignalContainer):
    def __init__(self):
        gtk.VBox.__init__(self)
        SignalContainer.__init__(self)

        # Init categorys.
        self.get_categorys()

        # load data.
        self.__load_webcast_query()

        # Init webcastbar.
        self.__init_webcastbar()

        # Init iconview.
        self.metro_view = self.get_icon_view()
        self.metro_view_sw = self.metro_view.get_scrolled_window()

        self.page_box = gtk.VBox()
        self.page_box.add(self.metro_view_sw)

        # webcasts view
        self.webcast_view = self.get_webcast_view()
        self.webcast_view_sw = self.webcast_view.get_scrolled_window()

        # collect view
        self.collected_db_file = get_config_file("favorite_webcasts.db")
        self.collected_view = self.get_webcast_view()
        self.collected_view_sw = self.collected_view.get_scrolled_window()

        # Init collect view.

        # init listview page.
        self.init_listview_page()
        Dispatcher.connect("change-webcast", self.on_dispatcher_change_webcast)
        WebcastDB.connect("changed", self.on_db_update_songs)

        body_paned = HPaned(handle_color=app_theme.get_color("panedHandler"),
                            enable_drag=True)
        body_paned.add1(self.webcastbar)
        body_paned.add2(self.page_box)
        self.add(body_paned)

    def get_categorys(self):
        lang = utils.get_system_lang()
        if lang.startswith("zh"):
            self.__categorys = ["region", "genre", "composite"]
            self.current_category = "region"
        else:
            self.__categorys = ["region_en", "genre_en"]
            self.current_category = "region_en"

        self.__category_gettexts = {
            "region": "地域分类",
            "genre": "流派分类",
            "region_en": _("Region"),
            "genre_en": _("Genre"),
            "composite": "综合分类",
            "finance": "财经",
            "sports": "体育",
            "music": "音乐",
            "news": "新闻",
            "network": "网络",
        }

    def __load_webcast_query(self):
        self.__db_query = WebcastQuery()
        if WebcastDB.isloaded():
            self.__on_db_loaded()
        else:
            WebcastDB.connect("loaded", lambda obj: self.__on_db_loaded())

    def __on_db_loaded(self):
        self.autoconnect(self.__db_query, "added", self.__on_added_songs)
        self.autoconnect(self.__db_query, "removed", self.__on_removed_songs)
        self.autoconnect(self.__db_query, "update-songs",
                         self.__on_update_songs)
        self.autoconnect(self.__db_query, "full-update", self.__on_full_update)
        self.__db_query.set_query()

    def __on_added_songs(self, db_query, songs):
        self.reload_flag = True

    def __on_removed_songs(self, db_query, songs):
        self.reload_flag = True

    def __on_update_songs(self, db_query, songs):
        self.reload_flag = True

    def __on_full_update(self, db_query):
        self.load_view_data()
        self.load_collect_data()

    def __init_webcastbar(self):
        self.webcastbar = TreeView(enable_drag_drop=False,
                                   enable_multiple_select=False)
        self.webcastbar.connect("single-click-item",
                                self.on_webcastbar_single_click_item)
        items = []
        for category in self.__categorys:
            items.append(
                CategoryTreeItem(self.__category_gettexts[category],
                                 category=category))
        items.append(CollectTreeItem(_("Favorites")))
        self.webcastbar.add_items(items)
        self.webcastbar.select_items([self.webcastbar.visible_items[0]])
        self.webcastbar.set_size_request(121, -1)
        self.webcastbar.draw_mask = self.on_webcastbar_draw_mask

    def on_webcastbar_draw_mask(self, cr, x, y, w, h):
        draw_alpha_mask(cr, x, y, w, h, "layoutRight")

    def on_webcastbar_single_click_item(self, widget, item, column, x, y):
        if hasattr(item, "collect_flag"):
            switch_tab(self.page_box, self.collected_view_sw)
        else:
            widget = self.page_box.get_children()[0]
            if widget != self.metro_view_sw:
                switch_tab(self.page_box, self.metro_view_sw)

            if self.current_category != item.category:
                self.current_category = item.category
                self.load_view_data()

    def init_listview_page(self):
        self.listview_page = gtk.VBox()
        self.text_prompt = TextPrompt("Default")
        prompt_align = set_widget_gravity(self.text_prompt,
                                          paddings=(10, 10, 0, 0))
        prompt_box = gtk.HBox()
        back_button = BackButton()
        back_button.connect("clicked", self.on_backbutton_clicked)
        back_button_align = set_widget_gravity(back_button,
                                               gravity=(0.5, 0.5, 0, 0),
                                               paddings=(0, 0, 10, 5))
        prompt_box.pack_start(back_button_align, False, True)
        prompt_box.pack_start(prompt_align, False, False)

        self.listview_page.pack_start(prompt_box, False, True)
        self.listview_page.pack_start(self.webcast_view_sw, True, True)

    def on_backbutton_clicked(self, widget):
        switch_tab(self.page_box, self.metro_view_sw)

    def switch_to_listview(self, category, title):
        self.text_prompt.set_text(title)
        self.webcast_view.clear()

        songs = self.__db_query.get_songs(category, title)
        self.webcast_view.add_webcasts(songs)
        switch_tab(self.page_box, self.listview_page)

    def load_view_data(self):
        self.metro_view.clear()
        if self.current_category == "composite":
            child_datas = self.__db_query.get_composite_categorys()
            gettext_datas = []
            for child in child_datas:
                gettext_datas.append((self.__category_gettexts[child], child))
            self.metro_view.add_composite_items(gettext_datas)

        else:
            child_datas = self.__db_query.get_info(self.current_category)[0]
            child_datas.sort(key=lambda x: locale.strxfrm(x))
            self.metro_view.add_webcast_items(child_datas)

    def load_collect_data(self):
        try:
            collected_objs = utils.load_db(self.collected_db_file)
        except:
            collected_objs = None

        if collected_objs:
            songs = [WebcastDB.get_song(uri) for uri in collected_objs]
        else:
            songs = None

        if songs:
            songs = [song for song in songs if song.get("collected", False)]
            if songs:
                self.collected_view.add_webcasts(songs)

    def get_icon_view(self):
        icon_view = WebcastIconView()
        icon_view.connect("single-click-item",
                          self.on_iconview_single_click_item)
        icon_view.connect("double-click-item",
                          self.on_iconview_single_click_item)
        return icon_view

    def on_iconview_single_click_item(self, widget, item, x, y):
        if item.is_composited:
            category = item.category
        else:
            category = self.current_category

        title = item.title
        if item.is_composited:
            self.switch_to_listview(category, title)
        else:
            self.switch_to_listview(category, title)

    def get_webcast_view(self):
        webcast_view = MultiDragWebcastView()
        webcast_view.keymap.update(
            {"BackSpace": lambda: self.on_backbutton_clicked(None)})
        return webcast_view

    def on_dispatcher_change_webcast(self, widget, song):
        item = self.collected_view.get_webcast_item(song)
        if item and not song.get("collected", False):
            self.collected_view.delete_items([item])
        elif song.get("collected", False):
            self.collected_view.add_webcasts([song])

    def on_db_update_songs(self, db, infos):
        for song, tags, new_tags in infos:
            if new_tags.has_key("collected"):
                item = self.collected_view.get_webcast_item(song)
                if item:
                    if not new_tags.get("collected", False):
                        self.collected_view.delete_items([item])
                else:
                    if new_tags.get("collected", False):
                        self.collected_view.add_webcasts([song])

    def save(self):
        songs = self.collected_view.get_webcasts()
        uris = [song.get("uri") for song in songs if song.get("uri")]
        utils.save_db(uris, self.collected_db_file)
class Region(gtk.Alignment):
    def __init__(self, connection=None):
        gtk.Alignment.__init__(self, 0, 0, 0, 0)

        #################
        self.provider_select = None
        self.connect('expose-event', self.expose_event)
        self.prop_dict = {}

        main_table = gtk.Table(2, 2, False)
        main_table.set_row_spacing(1, 10)
        main_table.set_col_spacings(4)
        self.add(main_table)
        
        self.country_tree = TreeView(enable_multiple_select=False,
                                     enable_drag_drop=False,
                                     )
        self.country_tree.set_expand_column(1)

        self.country_tree.set_size_request(365, 380)
        self.country_tree.draw_mask = self.draw_mask
        self.country_tree.connect("button-press-item", self.country_selected)
        left_box_align = gtk.Alignment(0, 0, 0, 0)
        left_box_align.set_padding(1,1,1,1)
        left_box_align.add(self.country_tree)
        left_box_align.show_all()

        left_box = gtk.VBox()
        # wrap title
        country_title = TitleBar(app_theme.get_pixbuf("network/globe-green.png"),
                                 _("Country or Region:"),
                                 has_separator=False)
        left_box.pack_start(country_title, False, False)
        left_box.pack_start(left_box_align, False, False)

        self.provider_tree = TreeView(enable_multiple_select=False,
                                     enable_drag_drop=False,
                                      )
        self.provider_tree.set_expand_column(0)
        self.provider_tree.set_size_request(365, 380)
        self.provider_tree.draw_mask = self.draw_mask
        self.provider_tree.connect("button-press-item", self.provider_selected)
        right_box_align = gtk.Alignment(0, 0, 0, 0)
        right_box_align.set_padding(1,1,1,1)
        right_box_align.add(self.provider_tree)
        right_box = gtk.VBox()
        # wrap title
        provider_title = TitleBar(app_theme.get_pixbuf("network/building.png"),
                                  _("Provider:"),
                                  has_separator=False)
        right_box.pack_start(provider_title, False, False)
        right_box.pack_start(right_box_align, False, False)
        
        
        main_left_align = gtk.Alignment(0, 0, 0, 0)
        main_left_align.set_padding(15, 0, 20, 0)
        main_left_align.add(left_box)
        main_table.attach(main_left_align, 0, 1, 0, 1)
        main_right_align = gtk.Alignment(0, 0, 0, 0)
        main_right_align.set_padding(15, 0, 0, 20)
        main_right_align.add(right_box)
        main_table.attach(main_right_align, 1, 2, 0, 1)

        hints = _("Tips:This assistant helps you easily set up a mobile broadband connection to a cellular network.")
            
        left_box_align.connect("expose-event", self.expose_outline)
        right_box_align.connect("expose-event", self.expose_outline)

        next_button = Button("Next")
        next_button.connect("clicked", self.next_button_clicked)
        
        self.foot_box = FootBox()
        self.foot_box.set_buttons([next_button])
        self.foot_box.set_tip(hints)
        main_table.attach(self.foot_box, 0, 2, 1, 2)

        self.show_all()
        #self.init()

    def expose_outline(self, widget, event):
        cr = widget.window.cairo_create()
        rect = widget.allocation
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            cr.set_source_rgb(*BORDER_COLOR)
            cr.rectangle(rect.x, rect.y, rect.width , rect.height )
            cr.stroke()

    def draw_mask(self, cr, x, y, w, h):
        cr.set_source_rgb(1, 1, 1)
        cr.rectangle(x, y, w, h)
        cr.fill()

    def expose_event(self, widget, event):
        cr = widget.window.cairo_create()
        rect = widget.allocation
        cr.set_source_rgb( 1, 1, 1) 
        cr.rectangle(rect.x, rect.y, rect.width, rect.height)
        cr.fill()

    def expose_hint_background(self, widget, event):
        bg_color = color_hex_to_cairo(TREEVIEW_BG_COLOR)
        cr = widget.window.cairo_create()
        rect = widget.allocation
        cr.set_source_rgb(*bg_color) 
        cr.rectangle(rect.x, rect.y, rect.width, rect.height)
        cr.fill()
        with cairo_disable_antialias(cr):
            cr.set_source_rgb(*BORDER_COLOR)
            cr.set_line_width(1)
            cr.rectangle(rect.x , rect.y, rect.width , rect.height -1)
            cr.stroke()


    def next_button_clicked(self, widget):
        # 检查是否选择了运营商
        if not self.provider_select:
            print "provider has not selected"
            return
        try:
            self.plan_select
        except:
            self.plan_select = None
        
        def add_keys(settings):
            self.prop_dict = settings
            
        username = self.__sp.get_provider_username(self.code, self.provider_select)
        password = self.__sp.get_provider_password(self.code, self.provider_select)
        add_keys({"cdma": {
                 "number": "#777",
                 "username": username,
                 "password": password}})
        provider_type = "cdma"
        if self.plan_select:
            self.prop_dict.pop("cdma")
            apn = self.plan_select
            index = self.__sp.get_provider_apns_name(self.code, self.provider_select).index(apn)
            (network_id, network_type) = self.__sp.get_provider_networks(self.code, self.provider_select)[index]
            add_keys({"gsm":{
                     "number": "*99#",
                     "username": username,
                     "password": password,
                     "apn": apn,
                     #"network_id": network_id,
                     "network_type": network_type}})
            provider_type = "gsm"

        #setting_page = nm_module.slider.get_page_by_name("setting")
        #broadband = setting_page.setting_group.get_broadband()
        if self.connection_type == None:
            new_connection = getattr(nm_module.nm_remote_settings, "new_%s_connection"%provider_type)()
            Dispatcher.emit("region-back", new_connection, self.prop_dict, provider_type)

            #setting_page.sidebar.new_connection_list[provider_type].append(new_connection)
            #setting_page.init(setting_page.sidebar.new_connection_list)
            #setting_page.sidebar.set_active(new_connection)
            #broadband.set_new_values(self.prop_dict, provider_type)
        else:
            Dispatcher.emit("region-back", self.connection, self.prop_dict, provider_type)

            #broadband.set_new_values(self.prop_dict, provider_type)

        nm_module.slider._slide_to_page("setting", "none")

    def init(self, connection):
        if connection == None:
            self.connection_type = None
        else:
            self.connection = connection
            mobile_type = connection.get_setting("connection").type
            self.connection_type = mobile_type
        Dispatcher.send_submodule_crumb(_("Region"), 2)

        from mm.provider import ServiceProviders
        self.__sp = ServiceProviders()
        self.country_list = self.__sp.get_country_name_list()
        self.country_tree.delete_all_items()
        self.country_tree.add_items([CountryItem(_(country)) for country in self.country_list])
        # add a bottom line for last item

        code = self.__sp.get_country_from_timezone()

        self.country_codes = self.__sp.get_country_list()
        try:
            selected_country = self.country_tree.visible_items[self.country_codes.index(code)]
            self.country_tree.select_items([selected_country])
            self.auto_scroll_to()
            self.country_tree.emit("button-press-item", selected_country, 0, 1, 1)
        except:
            pass

    def country_selected(self, widget, w, a, b, c):
        self.provider_tree.delete_all_items()
        self.code = self.country_codes[widget.select_rows[0]]
        if self.connection_type:
            self.provider_names = getattr(self.__sp, "get_country_%s_providers_name"%self.connection_type)(self.code)
        else:
            self.provider_names = self.__sp.get_country_providers_name(self.code)
        
        self.provider_select = None
        self.provider_tree.add_items([Item(p, self.__sp, self.code) for p in self.provider_names])
        self.provider_tree.show_all()

    def provider_selected(self, widget, item, column, offset_x, offset_y):
        if type(item) is Item:
            self.provider_select = item.content
            self.plan_select = None
        else:
            self.plan_select = item.content

    def auto_scroll_to(self):
        vadjust = self.country_tree.scrolled_window.get_vadjustment()
        upper = vadjust.upper
        page_size = vadjust.page_size

        vadjust.set_value(min(upper - page_size, (self.country_tree.select_rows[0]- 4)*30))