def __init__(self, chl): ''' Initialize ItemIcon class. @param pixbuf: Icon pixbuf. ''' gobject.GObject.__init__(self) MissionThread.__init__(self) self.padding_x = 10 self.padding_y = 10 self.default_width = 110 self.default_height = 95 self.pixbuf_rect = None self.hover_flag = False self.mask_flag = False self.highlight_flag = False self.pixbuf = None self.mask_pixbuf = None self.chl = chl self.title = chl.get("name", "") self.description = "%s首歌曲" % chl.get("song_num") self.create_cover_pixbuf() self.notify = CoverPopupNotify(chl) self.notify_timeout_id = None self.notify_timeout = 600
class CommonIconItem(gobject.GObject, MissionThread): __gsignals__ = { "redraw-request": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), } def __init__(self, chl): ''' Initialize ItemIcon class. @param pixbuf: Icon pixbuf. ''' gobject.GObject.__init__(self) MissionThread.__init__(self) self.padding_x = 10 self.padding_y = 10 self.default_width = 110 self.default_height = 95 self.pixbuf_rect = None self.hover_flag = False self.mask_flag = False self.highlight_flag = False self.pixbuf = None self.mask_pixbuf = None self.chl = chl self.title = chl.get("name", "") self.description = "%s首歌曲" % chl.get("song_num") self.create_cover_pixbuf() self.notify = CoverPopupNotify(chl) self.notify_timeout_id = None self.notify_timeout = 600 def create_cover_pixbuf(self): cover_path = DoubanCover.get_cover(self.chl, try_web=False) if cover_path: try: self.pixbuf = gtk.gdk.pixbuf_new_from_file(cover_path) self.is_loaded_cover = True except gobject.GError: self.pixbuf = app_theme.get_pixbuf( "radio/default_cover.png").get_pixbuf() self.is_loaded_cover = False else: self.pixbuf = app_theme.get_pixbuf( "radio/default_cover.png").get_pixbuf() self.is_loaded_cover = False def create_mask_pixbuf(self): if self.mask_pixbuf is None: self.mask_pixbuf = app_theme.get_pixbuf( "radio/covermask_play.png").get_pixbuf() def start_mission(self): cover_path = DoubanCover.get_cover(self.chl, try_web=True) if cover_path: self.delay_render_cover(cover_path) def delay_render_cover(self, cover_path): gobject.timeout_add(200 + random.randint(1, 10), self.render_cover, cover_path) @post_gui def render_cover(self, cover_path): try: pixbuf = gtk.gdk.pixbuf_new_from_file(cover_path) except: pass else: self.pixbuf = pixbuf self.emit_redraw_request() return False def emit_redraw_request(self): ''' Emit `redraw-request` signal. This is IconView interface, you should implement it. ''' self.emit("redraw-request") def get_width(self): ''' Get item width. This is IconView interface, you should implement it. ''' return self.default_width def get_height(self): ''' Get item height. This is IconView interface, you should implement it. ''' return self.default_height def render(self, cr, rect): ''' Render item. This is IconView interface, you should implement it. ''' # Draw cover. if self.pixbuf is None: self.create_cover_pixbuf() pixbuf_x = rect.x + (rect.width - self.pixbuf.get_width()) / 2 cr.save() cr.arc(pixbuf_x + self.pixbuf.get_width() / 2, rect.y + self.pixbuf.get_height() / 2, self.pixbuf.get_width() / 2, 0, 2 * math.pi) cr.clip() draw_pixbuf(cr, self.pixbuf, pixbuf_x, rect.y) cr.restore() if self.pixbuf_rect is None: self.pixbuf_rect = gtk.gdk.Rectangle( (rect.width - self.pixbuf.get_width()) / 2, 0, self.pixbuf.get_width(), self.pixbuf.get_height()) if self.mask_flag: if self.mask_pixbuf is None: self.create_mask_pixbuf() cr.save() cr.arc(pixbuf_x + self.pixbuf.get_width() / 2, rect.y + self.pixbuf.get_height() / 2, self.pixbuf.get_width() / 2, 0, 2 * math.pi) cr.clip() draw_pixbuf(cr, self.mask_pixbuf, pixbuf_x, rect.y) cr.restore() title_rect = gtk.gdk.Rectangle(rect.x + self.padding_x, rect.y + self.pixbuf.get_height() + 5, rect.width - self.padding_x * 2, 11) total_rect = gtk.gdk.Rectangle(title_rect.x, title_rect.y + 16, title_rect.width, 9) render_text( cr, utils.xmlescape(self.title), title_rect, # app_theme.get_color("labelText").get_color(), "#444444", 10) render_text(cr, utils.xmlescape(self.description), total_rect, app_theme.get_color("labelText").get_color(), 8) def icon_item_motion_notify(self, x, y): ''' Handle `motion-notify-event` signal. This is IconView interface, you should implement it. ''' if self.pointer_in_pixbuf(x, y): self.mask_flag = True else: self.mask_flag = False self.notify.hide_all() self.hover_flag = True self.emit_redraw_request() def try_show_notify(self, x, y): if not self.mask_flag: self.notify.hide_all() else: self.notify_timeout_id = gobject.timeout_add( self.notify_timeout, self.being_show_notify, x, y) def being_show_notify(self, x, y): if self.mask_flag: show_x = self.pixbuf_rect.x + self.pixbuf_rect.width + x show_y = self.pixbuf_rect.y + self.pixbuf_rect.height + y self.notify.show(show_x, show_y) def pointer_in_pixbuf(self, x, y): if self.pixbuf_rect is None: return False if self.pixbuf_rect.x <= x <= self.pixbuf_rect.x + self.pixbuf_rect.width and \ self.pixbuf_rect.y <= y <= self.pixbuf_rect.y + self.pixbuf_rect.height: return True else: return False def icon_item_lost_focus(self): ''' Lost focus. This is IconView interface, you should implement it. ''' self.hover_flag = False self.mask_flag = False self.emit_redraw_request() if self.notify_timeout_id is not None: gobject.source_remove(self.notify_timeout_id) self.notify_timeout_id = None self.notify.hide_all() def hide_notify(self): self.notify.hide_all() def icon_item_highlight(self): ''' Highlight item. This is IconView interface, you should implement it. ''' self.highlight_flag = True self.emit_redraw_request() def icon_item_normal(self): ''' Set item with normal status. This is IconView interface, you should implement it. ''' self.highlight_flag = False self.emit_redraw_request() def icon_item_button_press(self, x, y): ''' Handle button-press event. This is IconView interface, you should implement it. ''' pass def icon_item_button_release(self, x, y): ''' Handle button-release event. This is IconView interface, you should implement it. ''' pass def icon_item_single_click(self, x, y): ''' Handle single click event. This is IconView interface, you should implement it. ''' pass def icon_item_double_click(self, x, y): ''' Handle double click event. This is IconView interface, you should implement it. ''' pass def icon_item_release_resource(self): ''' Release item resource. If you have pixbuf in item, you should release memory resource like below code: >>> if self.pixbuf: >>> del self.pixbuf >>> self.pixbuf = None >>> >>> return True This is IconView interface, you should implement it. @return: Return True if do release work, otherwise return False. When this function return True, IconView will call function gc.collect() to release object to release memory. ''' if self.pixbuf: del self.pixbuf self.pixbuf = None if self.mask_pixbuf: del self.mask_pixbuf self.mask_pixbuf = None return True
class CommonIconItem(gobject.GObject, MissionThread): __gsignals__ = { "redraw-request" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),} def __init__(self, chl): ''' Initialize ItemIcon class. @param pixbuf: Icon pixbuf. ''' gobject.GObject.__init__(self) MissionThread.__init__(self) self.padding_x = 10 self.padding_y = 10 self.default_width = 110 self.default_height = 95 self.pixbuf_rect = None self.hover_flag = False self.mask_flag = False self.highlight_flag = False self.pixbuf = None self.mask_pixbuf = None self.chl = chl self.title = chl.get("name", "") self.description = "%s首歌曲" % chl.get("song_num") self.create_cover_pixbuf() self.notify = CoverPopupNotify(chl) self.notify_timeout_id = None self.notify_timeout = 600 def create_cover_pixbuf(self): cover_path = DoubanCover.get_cover(self.chl, try_web=False) if cover_path: try: self.pixbuf = gtk.gdk.pixbuf_new_from_file(cover_path) self.is_loaded_cover = True except gobject.GError: self.pixbuf = app_theme.get_pixbuf("radio/default_cover.png").get_pixbuf() self.is_loaded_cover = False else: self.pixbuf = app_theme.get_pixbuf("radio/default_cover.png").get_pixbuf() self.is_loaded_cover = False def create_mask_pixbuf(self): if self.mask_pixbuf is None: self.mask_pixbuf = app_theme.get_pixbuf("radio/covermask_play.png").get_pixbuf() def start_mission(self): cover_path = DoubanCover.get_cover(self.chl,try_web=True) if cover_path: self.delay_render_cover(cover_path) def delay_render_cover(self, cover_path): gobject.timeout_add(200 + random.randint(1, 10), self.render_cover, cover_path) @post_gui def render_cover(self,cover_path): try: pixbuf = gtk.gdk.pixbuf_new_from_file(cover_path) except: pass else: self.pixbuf = pixbuf self.emit_redraw_request() return False def emit_redraw_request(self): ''' Emit `redraw-request` signal. This is IconView interface, you should implement it. ''' self.emit("redraw-request") def get_width(self): ''' Get item width. This is IconView interface, you should implement it. ''' return self.default_width def get_height(self): ''' Get item height. This is IconView interface, you should implement it. ''' return self.default_height def render(self, cr, rect): ''' Render item. This is IconView interface, you should implement it. ''' # Draw cover. if self.pixbuf is None: self.create_cover_pixbuf() pixbuf_x = rect.x + (rect.width - self.pixbuf.get_width()) / 2 cr.save() cr.arc(pixbuf_x + self.pixbuf.get_width() / 2, rect.y + self.pixbuf.get_height() / 2, self.pixbuf.get_width() / 2, 0, 2 * math.pi) cr.clip() draw_pixbuf(cr, self.pixbuf, pixbuf_x, rect.y) cr.restore() if self.pixbuf_rect is None: self.pixbuf_rect = gtk.gdk.Rectangle((rect.width - self.pixbuf.get_width()) / 2, 0, self.pixbuf.get_width(), self.pixbuf.get_height()) if self.mask_flag: if self.mask_pixbuf is None: self.create_mask_pixbuf() cr.save() cr.arc(pixbuf_x + self.pixbuf.get_width() / 2, rect.y + self.pixbuf.get_height() / 2, self.pixbuf.get_width() / 2, 0, 2 * math.pi) cr.clip() draw_pixbuf(cr, self.mask_pixbuf, pixbuf_x, rect.y) cr.restore() title_rect = gtk.gdk.Rectangle(rect.x + self.padding_x, rect.y + self.pixbuf.get_height() + 5, rect.width - self.padding_x * 2, 11) total_rect = gtk.gdk.Rectangle(title_rect.x, title_rect.y + 16, title_rect.width, 9) render_text(cr, utils.xmlescape(self.title), title_rect, # app_theme.get_color("labelText").get_color(), "#444444", 10) render_text(cr, utils.xmlescape(self.description), total_rect, app_theme.get_color("labelText").get_color(), 8) def icon_item_motion_notify(self, x, y): ''' Handle `motion-notify-event` signal. This is IconView interface, you should implement it. ''' if self.pointer_in_pixbuf(x, y): self.mask_flag = True else: self.mask_flag = False self.notify.hide_all() self.hover_flag = True self.emit_redraw_request() def try_show_notify(self, x, y): if not self.mask_flag: self.notify.hide_all() else: self.notify_timeout_id = gobject.timeout_add(self.notify_timeout, self.being_show_notify, x, y) def being_show_notify(self, x, y): if self.mask_flag: show_x = self.pixbuf_rect.x + self.pixbuf_rect.width + x show_y = self.pixbuf_rect.y + self.pixbuf_rect.height + y self.notify.show(show_x, show_y) def pointer_in_pixbuf(self, x, y): if self.pixbuf_rect is None: return False if self.pixbuf_rect.x <= x <= self.pixbuf_rect.x + self.pixbuf_rect.width and \ self.pixbuf_rect.y <= y <= self.pixbuf_rect.y + self.pixbuf_rect.height: return True else: return False def icon_item_lost_focus(self): ''' Lost focus. This is IconView interface, you should implement it. ''' self.hover_flag = False self.mask_flag = False self.emit_redraw_request() if self.notify_timeout_id is not None: gobject.source_remove(self.notify_timeout_id) self.notify_timeout_id = None self.notify.hide_all() def hide_notify(self): self.notify.hide_all() def icon_item_highlight(self): ''' Highlight item. This is IconView interface, you should implement it. ''' self.highlight_flag = True self.emit_redraw_request() def icon_item_normal(self): ''' Set item with normal status. This is IconView interface, you should implement it. ''' self.highlight_flag = False self.emit_redraw_request() def icon_item_button_press(self, x, y): ''' Handle button-press event. This is IconView interface, you should implement it. ''' pass def icon_item_button_release(self, x, y): ''' Handle button-release event. This is IconView interface, you should implement it. ''' pass def icon_item_single_click(self, x, y): ''' Handle single click event. This is IconView interface, you should implement it. ''' pass def icon_item_double_click(self, x, y): ''' Handle double click event. This is IconView interface, you should implement it. ''' pass def icon_item_release_resource(self): ''' Release item resource. If you have pixbuf in item, you should release memory resource like below code: >>> if self.pixbuf: >>> del self.pixbuf >>> self.pixbuf = None >>> >>> return True This is IconView interface, you should implement it. @return: Return True if do release work, otherwise return False. When this function return True, IconView will call function gc.collect() to release object to release memory. ''' if self.pixbuf: del self.pixbuf self.pixbuf = None if self.mask_pixbuf: del self.mask_pixbuf self.mask_pixbuf = None return True