class InstallItem(TreeItem): ''' class docs ''' STATUS_READY_DOWNLOAD= 1 STATUS_PARSE_DOWNLOAD_FAILED = 2 STATUS_DOWNLOAD_FAILED = 3 STATUS_WAIT_DOWNLOAD = 4 STATUS_IN_DOWNLOAD = 5 STATUS_STOP_DOWNLOAD = 6 STATUS_WAIT_INSTALL = 7 STATUS_STOP_WAIT_INSTALL = 8 STATUS_IN_INSTALL = 9 STATUS_INSTALL_FINISH = 10 STATUS_INSTALL_FAILED = 11 STATUS_PADDING_X = 15 def __init__(self, pkg_name, pkg_version, data_manager): ''' init docs ''' TreeItem.__init__(self) self.pkg_name = pkg_name self.pkg_version = pkg_version self.data_manager = data_manager self.icon_pixbuf = None info = self.data_manager.get_item_pkg_info(self.pkg_name) self.alias_name = info[1] self.short_desc = info[2] self.star_level = get_star_level(5.0) self.star_buffer = DscStarBuffer(pkg_name) self.grade_star = 0 self.status = self.STATUS_READY_DOWNLOAD self.status_text = _("Dependencies analyzing") self.progress_buffer = ProgressBuffer() button_pixbuf = app_theme.get_pixbuf("button/start_normal.png").get_pixbuf() (self.button_width, self.button_height) = button_pixbuf.get_width(), button_pixbuf.get_height() self.button_status = BUTTON_NORMAL ### TODO: is_installed status self.install_status = json.dumps([]) self.desktops = [] def handle_pkg_status(self, status, success): if success: self.install_status= str(status) try: self.desktops = json.loads(self.install_status) self.desktops = self.data_manager.get_pkg_desktop_info(self.desktops) except: pass self.emit_redraw_request() else: utils.global_logger.logerror("%s: get_pkg_installed handle_dbus_error" % self.pkg_name) utils.global_logger.logerror(status) def render_pkg_info(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.icon_pixbuf == None: self.icon_pixbuf = gtk.gdk.pixbuf_new_from_file(get_icon_pixbuf_path(self.pkg_name)) render_pkg_info(cr, rect, self.alias_name, self.pkg_name, self.icon_pixbuf, self.pkg_version, self.short_desc, ITEM_PKG_OFFSET_X) def render_pkg_status(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.status == self.STATUS_READY_DOWNLOAD: draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_WAIT_DOWNLOAD: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (rect.height - pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_IN_DOWNLOAD: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (rect.height - pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_STOP_DOWNLOAD: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_DOWNLOAD_FAILED: # Draw star. draw_text( cr, self.status_text, rect.x, rect.y, get_content_size(self.status_text)[0], ITEM_HEIGHT, text_color="#ff0000", ) if self.button_status == BUTTON_NORMAL: status = "normal" elif self.button_status == BUTTON_HOVER: status = "hover" elif self.button_status == BUTTON_PRESS: status = "press" pixbuf = app_theme.get_pixbuf("button/install_%s.png" % (status, )).get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), rect.y + (rect.height - pixbuf.get_height()) / 2 ) elif self.status == self.STATUS_WAIT_INSTALL: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (rect.height - pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_STOP_WAIT_INSTALL: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_IN_INSTALL: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_INSTALL_FINISH: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) # Draw button. name = "" draw_str = "" if self.install_status == "uninstalled": name = "button/install" elif self.install_status == "unknown": draw_str = _("Installed") else: if self.desktops: name = "button/start" else: draw_str = _("Installed") if name: if self.button_status == BUTTON_NORMAL: status = "normal" elif self.button_status == BUTTON_HOVER: status = "hover" elif self.button_status == BUTTON_PRESS: status = "press" pixbuf = app_theme.get_pixbuf("%s_%s.png" % (name, status)).get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), rect.y + (ITEM_HEIGHT - self.button_height) / 2, ) else: str_width, str_height = get_content_size(draw_str, 10) draw_text( cr, draw_str, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - str_width, rect.y + (rect.height - str_height) / 2, str_width, str_height, alignment=pango.ALIGN_CENTER, ) elif self.status == self.STATUS_PARSE_DOWNLOAD_FAILED: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) def get_height(self): return ITEM_HEIGHT def get_column_widths(self): return [ITEM_INFO_AREA_WIDTH, ITEM_STAR_AREA_WIDTH + ITEM_BUTTON_AREA_WIDTH] def get_column_renders(self): return [self.render_pkg_info, self.render_pkg_status] def unselect(self): pass def select(self): pass def unhover(self, column, offset_x, offset_y): pass def hover(self, column, offset_x, offset_y): pass def motion_notify(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) else: global_event.emit("set-cursor", None) else: if self.status == self.STATUS_INSTALL_FINISH: if self.desktops: if self.is_in_button_area(column, offset_x, offset_y): self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self) elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star if self.redraw_request_callback: self.redraw_request_callback(self) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level if self.redraw_request_callback: self.redraw_request_callback(self) elif self.status == self.STATUS_DOWNLOAD_FAILED: if self.is_in_button_area(column, offset_x, offset_y): self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self) elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) elif self.status == self.STATUS_READY_DOWNLOAD: if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star if self.redraw_request_callback: self.redraw_request_callback(self) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level if self.redraw_request_callback: self.redraw_request_callback(self) def button_press(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) else: if self.status == self.STATUS_WAIT_DOWNLOAD: if self.is_stop_button_can_click(column, offset_x, offset_y): self.status = self.STATUS_STOP_DOWNLOAD self.status_text = _("Download was interrupted") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("remove-wait-download", [self.pkg_name]) global_event.emit("request-stop-install-actions", [self.pkg_name]) elif self.is_in_star_area(column, offset_x, offset_y): global_event.emit("grade-pkg", self.pkg_name, self.grade_star) elif self.status == self.STATUS_IN_DOWNLOAD: if self.is_stop_button_can_click(column, offset_x, offset_y): self.status = self.STATUS_STOP_DOWNLOAD self.status_text = _("Download was interrupted") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("stop-download-pkg", [self.pkg_name]) global_event.emit("request-stop-install-actions", [self.pkg_name]) elif self.status == self.STATUS_DOWNLOAD_FAILED: if self.is_in_button_area(column, offset_x, offset_y): global_event.emit("install-pkg", [self.pkg_name]) elif self.status == self.STATUS_WAIT_INSTALL: if self.is_stop_button_can_click(column, offset_x, offset_y): self.status = self.STATUS_STOP_WAIT_INSTALL self.status_text = _("Installation was interrupted") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("remove-wait-action", [(self.pkg_name, ACTION_INSTALL)]) global_event.emit("request-stop-install-actions", [self.pkg_name]) elif self.status == self.STATUS_INSTALL_FINISH: if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("grade-pkg", self.pkg_name, self.grade_star) elif self.is_in_button_area(column, offset_x, offset_y): if self.desktops: global_event.emit("start-pkg", self.alias_name, self.desktops, self.get_offset_with_button(offset_x, offset_y)) def get_offset_with_button(self, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/start_normal.png").get_pixbuf() popup_x = self.get_column_widths()[1] - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width() / 2 popup_y = (ITEM_HEIGHT - pixbuf.get_height()) / 2 return (offset_x, offset_y, popup_x, popup_y) def button_release(self, column, offset_x, offset_y): pass def single_click(self, column, offset_x, offset_y): pass def double_click(self, column, offset_x, offset_y): pass def is_in_star_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect((offset_x, offset_y), (0, (ITEM_HEIGHT - STAR_SIZE) / 2, ITEM_STAR_AREA_WIDTH, STAR_SIZE))) def is_in_button_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect((offset_x, offset_y), (self.get_column_widths()[column] - ITEM_BUTTON_PADDING_RIGHT - self.button_width, (ITEM_HEIGHT - self.button_height) / 2, self.button_width, self.button_height))) def is_stop_button_can_click(self, column, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() return (column == 1 and is_in_rect((offset_x, offset_y), (self.get_column_widths()[column] - ITEM_CANCEL_BUTTON_PADDING_RIGHT, (ITEM_HEIGHT - pixbuf.get_height()) / 2, pixbuf.get_width(), pixbuf.get_height()))) def download_ready(self): self.status = self.STATUS_READY_DOWNLOAD self.status_text = _("Dependencies analyzing") if self.redraw_request_callback: self.redraw_request_callback(self) def download_wait(self): self.status = self.STATUS_WAIT_DOWNLOAD self.status_text = _("Waiting for download") if self.redraw_request_callback: self.redraw_request_callback(self) def download_start(self): self.status = self.STATUS_IN_DOWNLOAD self.status_text = _("Downloading") if self.redraw_request_callback: self.redraw_request_callback(self) def download_failed(self): self.status = self.STATUS_DOWNLOAD_FAILED self.status_text = _("Download failed") if self.redraw_request_callback: self.redraw_request_callback(self) def download_update(self, percent, speed): self.status = self.STATUS_IN_DOWNLOAD self.progress_buffer.progress = percent self.status_text = "%s/s" % (format_file_size(speed)) if self.redraw_request_callback: self.redraw_request_callback(self) def download_finish(self): self.status = self.STATUS_WAIT_INSTALL self.progress_buffer.progress = 0 self.status_text = _("Waiting for installation") if self.redraw_request_callback: self.redraw_request_callback(self) def download_stop(self): pass def download_parse_failed(self): self.status = self.STATUS_PARSE_DOWNLOAD_FAILED self.status_text = _("Dependencies analysis failed") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("request-clear-failed-action", self.pkg_name, ACTION_INSTALL) def action_start(self): self.status = self.STATUS_IN_INSTALL self.status_text = _("Installing") if self.redraw_request_callback: self.redraw_request_callback(self) def action_update(self, percent): self.status = self.STATUS_IN_INSTALL self.status_text = _("Installing") self.progress_buffer.progress = percent if self.redraw_request_callback: self.redraw_request_callback(self) def action_finish(self): self.status = self.STATUS_INSTALL_FINISH self.progress_buffer.progress = 100 self.status_text = _("Installation completed") if self.redraw_request_callback: self.redraw_request_callback(self) self.data_manager.get_pkg_installed(self.pkg_name, self.handle_pkg_status) def is_in_name_area(self, column, offset_x, offset_y): (name_width, name_height) = get_content_size(self.alias_name, NAME_SIZE) return (column == 0 and is_in_rect((offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X + ICON_SIZE + ITEM_PADDING_MIDDLE, ITEM_PADDING_Y, name_width, NAME_SIZE))) def is_in_icon_area(self, column, offset_x, offset_y): return (column == 0 and self.icon_pixbuf != None and is_in_rect((offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X, ITEM_PADDING_Y, self.icon_pixbuf.get_width(), self.icon_pixbuf.get_height()))) def 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 TreeView interface, you should implement it. @return: Return True if do release work, otherwise return False. When this function return True, TreeView will call function gc.collect() to release object to release memory. ''' if self.icon_pixbuf: del self.icon_pixbuf self.icon_pixbuf = None return True
class UninstallItem(TreeItem): ''' class docs ''' STATUS_NORMAL = 1 STATUS_CONFIRM = 2 STATUS_WAIT_ACTION = 3 STATUS_IN_ACTION = 4 STATUS_PADDING_X = 15 def __init__(self, pkg_name, pkg_version, data_manager): ''' init docs ''' TreeItem.__init__(self) self.pkg_name = pkg_name self.pkg_version = pkg_version self.data_manager = data_manager self.icon_pixbuf = None (self.short_desc, star, self.alias_name) = data_manager.get_item_pkg_info(self.pkg_name) self.star_level = get_star_level(star) self.star_buffer = DscStarBuffer(pkg_name) self.grade_star = 0 button_pixbuf = app_theme.get_pixbuf("button/uninstall_normal.png").get_pixbuf() (self.button_width, self.button_height) = button_pixbuf.get_width(), button_pixbuf.get_height() self.button_status = BUTTON_NORMAL self.status = self.STATUS_NORMAL self.status_text = "" self.progress_buffer = ProgressBuffer() #self.action_wait() def render_pkg_info(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.icon_pixbuf == None: self.icon_pixbuf = gtk.gdk.pixbuf_new_from_file(get_icon_pixbuf_path(self.pkg_name)) render_pkg_info(cr, rect, self.alias_name, self.pkg_name, self.icon_pixbuf, self.pkg_version, self.short_desc, ITEM_PKG_OFFSET_X) def render_pkg_status(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.status == self.STATUS_CONFIRM: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) confirm_pixbuf = app_theme.get_pixbuf("button/uninstall_confirm.png").get_pixbuf() cancel_pixbuf = app_theme.get_pixbuf("button/uninstall_cancel.png").get_pixbuf() draw_pixbuf( cr, confirm_pixbuf, rect.x + rect.width - ITEM_CONFIRM_BUTTON_PADDING_RIGHT, rect.y + (ITEM_HEIGHT - confirm_pixbuf.get_height()) / 2, ) draw_pixbuf( cr, cancel_pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (ITEM_HEIGHT - cancel_pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_IN_ACTION: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT, ) elif self.status == self.STATUS_WAIT_ACTION: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT, ) cancel_pixbuf = app_theme.get_pixbuf("button/uninstall_cancel.png").get_pixbuf() draw_pixbuf( cr, cancel_pixbuf, rect.x + rect.width - 50, rect.y + (ITEM_HEIGHT - cancel_pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_NORMAL: # Draw star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) # Draw button. if self.button_status == BUTTON_NORMAL: pixbuf = app_theme.get_pixbuf("button/uninstall_normal.png").get_pixbuf() elif self.button_status == BUTTON_HOVER: pixbuf = app_theme.get_pixbuf("button/uninstall_hover.png").get_pixbuf() elif self.button_status == BUTTON_PRESS: pixbuf = app_theme.get_pixbuf("button/uninstall_press.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), rect.y + (ITEM_HEIGHT - self.button_height) / 2, ) def get_height(self): return ITEM_HEIGHT def get_column_widths(self): return [ITEM_INFO_AREA_WIDTH, ITEM_STAR_AREA_WIDTH + ITEM_BUTTON_AREA_WIDTH] def get_column_renders(self): return [self.render_pkg_info, self.render_pkg_status] def unselect(self): pass def select(self): pass def unhover(self, column, offset_x, offset_y): pass def hover(self, column, offset_x, offset_y): pass def motion_notify(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) else: global_event.emit("set-cursor", None) else: if self.status == self.STATUS_NORMAL: if self.is_in_button_area(column, offset_x, offset_y): self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self) elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star if self.redraw_request_callback: self.redraw_request_callback(self) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level if self.redraw_request_callback: self.redraw_request_callback(self) def button_press(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) else: if self.status == self.STATUS_NORMAL: if self.is_in_button_area(column, offset_x, offset_y): self.status = self.STATUS_CONFIRM if self.redraw_request_callback: self.redraw_request_callback(self) elif self.is_in_star_area(column, offset_x, offset_y): global_event.emit("grade-pkg", self.pkg_name, self.grade_star) elif self.status == self.STATUS_CONFIRM: if self.is_confirm_button_area(column, offset_x, offset_y): self.status = self.STATUS_WAIT_ACTION self.status_text = _("Waiting for uninstall") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("uninstall-pkg", self.pkg_name, get_purg_flag()) elif self.is_cancel_button_area(column, offset_x, offset_y): self.status = self.STATUS_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) elif self.status == self.STATUS_WAIT_ACTION: if self.is_cancel_button_area(column, offset_x, offset_y): self.status = self.STATUS_NORMAL global_event.emit("remove-wait-action", [(str((self.pkg_name, ACTION_UNINSTALL)))]) if self.redraw_request_callback: self.redraw_request_callback(self) def button_release(self, column, offset_x, offset_y): pass def single_click(self, column, offset_x, offset_y): pass def double_click(self, column, offset_x, offset_y): pass def is_in_star_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect((offset_x, offset_y), (0, (ITEM_HEIGHT - STAR_SIZE) / 2, ITEM_STAR_AREA_WIDTH, STAR_SIZE))) def is_in_button_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect((offset_x, offset_y), (self.get_column_widths()[column] - ITEM_BUTTON_PADDING_RIGHT - self.button_width, (ITEM_HEIGHT - self.button_height) / 2, self.button_width, self.button_height))) def is_confirm_button_area(self, column, offset_x, offset_y): confirm_pixbuf = app_theme.get_pixbuf("button/uninstall_confirm.png").get_pixbuf() return (column == 1 and is_in_rect((offset_x, offset_y), (self.get_column_widths()[column] - ITEM_CONFIRM_BUTTON_PADDING_RIGHT, (ITEM_HEIGHT - confirm_pixbuf.get_height()) / 2, confirm_pixbuf.get_width(), confirm_pixbuf.get_height()))) def is_cancel_button_area(self, column, offset_x, offset_y): cancel_pixbuf = app_theme.get_pixbuf("button/uninstall_cancel.png").get_pixbuf() return (column == 1 and is_in_rect((offset_x, offset_y), (self.get_column_widths()[column] - ITEM_CANCEL_BUTTON_PADDING_RIGHT, (ITEM_HEIGHT - cancel_pixbuf.get_height()) / 2, cancel_pixbuf.get_width(), cancel_pixbuf.get_height()))) def is_in_name_area(self, column, offset_x, offset_y): (name_width, name_height) = get_content_size(self.alias_name, NAME_SIZE) return (column == 0 and is_in_rect((offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X + ICON_SIZE + ITEM_PADDING_MIDDLE, ITEM_PADDING_Y, name_width, NAME_SIZE))) def is_in_icon_area(self, column, offset_x, offset_y): return (column == 0 and self.icon_pixbuf != None and is_in_rect((offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X, ITEM_PADDING_Y, self.icon_pixbuf.get_width(), self.icon_pixbuf.get_height()))) def action_wait(self): self.status = self.STATUS_WAIT_ACTION self.status_text = _("Waiting for uninstall") if self.redraw_request_callback: self.redraw_request_callback(self) def action_start(self): self.status = self.STATUS_IN_ACTION self.status_text = _("Uninstalling") if self.redraw_request_callback: self.redraw_request_callback(self) def action_update(self, percent): self.progress_buffer.progress = percent self.status_text = _("Uninstalling") if self.redraw_request_callback: self.redraw_request_callback(self) def action_finish(self): self.progress_buffer.progress = 100 self.status_text = _("Uninstall successful") if self.redraw_request_callback: self.redraw_request_callback(self) def 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 TreeView interface, you should implement it. @return: Return True if do release work, otherwise return False. When this function return True, TreeView will call function gc.collect() to release object to release memory. ''' if self.icon_pixbuf: del self.icon_pixbuf self.icon_pixbuf = None return True
class InstallItem(TreeItem): ''' class docs ''' STATUS_READY_DOWNLOAD = 1 STATUS_PARSE_DOWNLOAD_FAILED = 2 STATUS_DOWNLOAD_FAILED = 3 STATUS_WAIT_DOWNLOAD = 4 STATUS_IN_DOWNLOAD = 5 STATUS_STOP_DOWNLOAD = 6 STATUS_WAIT_INSTALL = 7 STATUS_STOP_WAIT_INSTALL = 8 STATUS_IN_INSTALL = 9 STATUS_INSTALL_FINISH = 10 STATUS_INSTALL_FAILED = 11 STATUS_PADDING_X = 15 def __init__(self, pkg_name, pkg_version, data_manager): ''' init docs ''' TreeItem.__init__(self) self.pkg_name = pkg_name self.pkg_version = pkg_version self.data_manager = data_manager self.icon_pixbuf = None info = self.data_manager.get_item_pkg_info(self.pkg_name) self.alias_name = info[1] self.short_desc = info[2] self.star_level = get_star_level(5.0) self.star_buffer = DscStarBuffer(pkg_name) self.grade_star = 0 self.status = self.STATUS_READY_DOWNLOAD self.status_text = _("Dependencies analyzing") self.progress_buffer = ProgressBuffer() button_pixbuf = app_theme.get_pixbuf( "button/start_normal.png").get_pixbuf() (self.button_width, self.button_height ) = button_pixbuf.get_width(), button_pixbuf.get_height() self.button_status = BUTTON_NORMAL ### TODO: is_installed status self.install_status = json.dumps([]) self.desktops = [] def handle_pkg_status(self, status, success): if success: self.install_status = str(status) try: self.desktops = json.loads(self.install_status) self.desktops = self.data_manager.get_pkg_desktop_info( self.desktops) except: pass self.emit_redraw_request() else: utils.global_logger.error( "%s: get_pkg_installed handle_dbus_error" % self.pkg_name) utils.global_logger.error(status) def render_pkg_info(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.icon_pixbuf == None: self.icon_pixbuf = gtk.gdk.pixbuf_new_from_file( get_icon_pixbuf_path(self.pkg_name)) render_pkg_info(cr, rect, self.alias_name, self.pkg_name, self.icon_pixbuf, self.pkg_version, self.short_desc, ITEM_PKG_OFFSET_X) def render_pkg_status(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.status == self.STATUS_READY_DOWNLOAD: draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_WAIT_DOWNLOAD: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (rect.height - pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_IN_DOWNLOAD: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (rect.height - pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_STOP_DOWNLOAD: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_DOWNLOAD_FAILED: # Draw star. draw_text( cr, self.status_text, rect.x, rect.y, get_content_size(self.status_text)[0], ITEM_HEIGHT, text_color="#ff0000", ) if self.button_status == BUTTON_NORMAL: status = "normal" elif self.button_status == BUTTON_HOVER: status = "hover" elif self.button_status == BUTTON_PRESS: status = "press" pixbuf = app_theme.get_pixbuf("button/install_%s.png" % (status, )).get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), rect.y + (rect.height - pixbuf.get_height()) / 2) elif self.status == self.STATUS_WAIT_INSTALL: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (rect.height - pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_STOP_WAIT_INSTALL: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_IN_INSTALL: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) elif self.status == self.STATUS_INSTALL_FINISH: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) # Draw button. name = "" draw_str = "" if self.install_status == "uninstalled": name = "button/install" elif self.install_status == "unknown": draw_str = _("Installed") else: if self.desktops: name = "button/start" else: draw_str = _("Installed") if name: if self.button_status == BUTTON_NORMAL: status = "normal" elif self.button_status == BUTTON_HOVER: status = "hover" elif self.button_status == BUTTON_PRESS: status = "press" pixbuf = app_theme.get_pixbuf("%s_%s.png" % (name, status)).get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), rect.y + (ITEM_HEIGHT - self.button_height) / 2, ) else: str_width, str_height = get_content_size(draw_str, 10) draw_text( cr, draw_str, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - str_width, rect.y + (rect.height - str_height) / 2, str_width, str_height, alignment=pango.ALIGN_CENTER, ) elif self.status == self.STATUS_PARSE_DOWNLOAD_FAILED: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH - self.STATUS_PADDING_X, ITEM_HEIGHT, ) def get_height(self): return ITEM_HEIGHT def get_column_widths(self): return [ ITEM_INFO_AREA_WIDTH, ITEM_STAR_AREA_WIDTH + ITEM_BUTTON_AREA_WIDTH ] def get_column_renders(self): return [self.render_pkg_info, self.render_pkg_status] def unselect(self): pass def select(self): pass def unhover(self, column, offset_x, offset_y): pass def hover(self, column, offset_x, offset_y): pass def motion_notify(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) else: global_event.emit("set-cursor", None) else: if self.status == self.STATUS_INSTALL_FINISH: if self.desktops: if self.is_in_button_area(column, offset_x, offset_y): self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self) elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star if self.redraw_request_callback: self.redraw_request_callback(self) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level if self.redraw_request_callback: self.redraw_request_callback(self) elif self.status == self.STATUS_DOWNLOAD_FAILED: if self.is_in_button_area(column, offset_x, offset_y): self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self) elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) elif self.status == self.STATUS_READY_DOWNLOAD: if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star if self.redraw_request_callback: self.redraw_request_callback(self) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level if self.redraw_request_callback: self.redraw_request_callback(self) def button_press(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) else: if self.status == self.STATUS_WAIT_DOWNLOAD: if self.is_stop_button_can_click(column, offset_x, offset_y): self.status = self.STATUS_STOP_DOWNLOAD self.status_text = _("Download was interrupted") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("remove-wait-download", [self.pkg_name]) global_event.emit("request-stop-install-actions", [self.pkg_name]) elif self.is_in_star_area(column, offset_x, offset_y): global_event.emit("grade-pkg", self.pkg_name, self.grade_star) elif self.status == self.STATUS_IN_DOWNLOAD: if self.is_stop_button_can_click(column, offset_x, offset_y): self.status = self.STATUS_STOP_DOWNLOAD self.status_text = _("Download was interrupted") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("stop-download-pkg", [self.pkg_name]) global_event.emit("request-stop-install-actions", [self.pkg_name]) elif self.status == self.STATUS_DOWNLOAD_FAILED: if self.is_in_button_area(column, offset_x, offset_y): global_event.emit("install-pkg", [self.pkg_name]) elif self.status == self.STATUS_WAIT_INSTALL: if self.is_stop_button_can_click(column, offset_x, offset_y): self.status = self.STATUS_STOP_WAIT_INSTALL self.status_text = _("Installation was interrupted") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("remove-wait-action", [(self.pkg_name, ACTION_INSTALL)]) global_event.emit("request-stop-install-actions", [self.pkg_name]) elif self.status == self.STATUS_INSTALL_FINISH: if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("grade-pkg", self.pkg_name, self.grade_star) elif self.is_in_button_area(column, offset_x, offset_y): if self.desktops: global_event.emit( "start-pkg", self.alias_name, self.desktops, self.get_offset_with_button(offset_x, offset_y)) def get_offset_with_button(self, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/start_normal.png").get_pixbuf() popup_x = self.get_column_widths( )[1] - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width() / 2 popup_y = (ITEM_HEIGHT - pixbuf.get_height()) / 2 return (offset_x, offset_y, popup_x, popup_y) def button_release(self, column, offset_x, offset_y): pass def single_click(self, column, offset_x, offset_y): pass def double_click(self, column, offset_x, offset_y): pass def is_in_star_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect( (offset_x, offset_y), (0, (ITEM_HEIGHT - STAR_SIZE) / 2, ITEM_STAR_AREA_WIDTH, STAR_SIZE))) def is_in_button_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect( (offset_x, offset_y), (self.get_column_widths()[column] - ITEM_BUTTON_PADDING_RIGHT - self.button_width, (ITEM_HEIGHT - self.button_height) / 2, self.button_width, self.button_height))) def is_stop_button_can_click(self, column, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/stop.png").get_pixbuf() return (column == 1 and is_in_rect( (offset_x, offset_y), (self.get_column_widths()[column] - ITEM_CANCEL_BUTTON_PADDING_RIGHT, (ITEM_HEIGHT - pixbuf.get_height()) / 2, pixbuf.get_width(), pixbuf.get_height()))) def download_ready(self): self.status = self.STATUS_READY_DOWNLOAD self.status_text = _("Dependencies analyzing") if self.redraw_request_callback: self.redraw_request_callback(self) def download_wait(self): self.status = self.STATUS_WAIT_DOWNLOAD self.status_text = _("Waiting for download") if self.redraw_request_callback: self.redraw_request_callback(self) def download_start(self): self.status = self.STATUS_IN_DOWNLOAD self.status_text = _("Downloading") if self.redraw_request_callback: self.redraw_request_callback(self) def download_failed(self): self.status = self.STATUS_DOWNLOAD_FAILED self.status_text = _("Download failed") if self.redraw_request_callback: self.redraw_request_callback(self) def download_update(self, percent, speed): self.status = self.STATUS_IN_DOWNLOAD self.progress_buffer.progress = percent self.status_text = "%s/s" % (format_file_size(speed)) if self.redraw_request_callback: self.redraw_request_callback(self) def download_finish(self): self.status = self.STATUS_WAIT_INSTALL self.progress_buffer.progress = 0 self.status_text = _("Waiting for installation") if self.redraw_request_callback: self.redraw_request_callback(self) def download_stop(self): pass def download_parse_failed(self): self.status = self.STATUS_PARSE_DOWNLOAD_FAILED self.status_text = _("Dependencies analysis failed") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("request-clear-failed-action", self.pkg_name, ACTION_INSTALL) def action_start(self): self.status = self.STATUS_IN_INSTALL self.status_text = _("Installing") if self.redraw_request_callback: self.redraw_request_callback(self) def action_update(self, percent): self.status = self.STATUS_IN_INSTALL self.status_text = _("Installing") self.progress_buffer.progress = percent if self.redraw_request_callback: self.redraw_request_callback(self) def action_finish(self): self.status = self.STATUS_INSTALL_FINISH self.progress_buffer.progress = 100 self.status_text = _("Installation completed") if self.redraw_request_callback: self.redraw_request_callback(self) self.data_manager.get_pkg_installed(self.pkg_name, self.handle_pkg_status) def is_in_name_area(self, column, offset_x, offset_y): (name_width, name_height) = get_content_size(self.alias_name, NAME_SIZE) return (column == 0 and is_in_rect( (offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X + ICON_SIZE + ITEM_PADDING_MIDDLE, ITEM_PADDING_Y, name_width, NAME_SIZE))) def is_in_icon_area(self, column, offset_x, offset_y): return (column == 0 and self.icon_pixbuf != None and is_in_rect( (offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X, ITEM_PADDING_Y, self.icon_pixbuf.get_width(), self.icon_pixbuf.get_height()))) def 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 TreeView interface, you should implement it. @return: Return True if do release work, otherwise return False. When this function return True, TreeView will call function gc.collect() to release object to release memory. ''' if self.icon_pixbuf: del self.icon_pixbuf self.icon_pixbuf = None return True
class PkgIconItem(IconItem): ''' class docs ''' ALIAS_NAME_SIZE = 12 PADDING_X = 10 PADDING_Y = 10 PADDING_MIDDLE = 10 BUTTON_PADDING_X = ITEM_PADDING_X BUTTON_PADDING_Y = 60 BUTTON_WIDTH = 48 BUTTON_HEIGHT = 18 DRAW_ICON_SIZE = 48 DRAW_PADDING_LEFT = 20 DRAW_PADDING_RIGHT = 10 DRAW_PADDING_Y = 16 DRAW_BUTTON_PADDING_Y = 13 DRAW_INFO_PADDING_X = 15 DRAW_STAR_PADDING_Y = 40 DRAW_LONG_DESC_PADDING_Y = 68 def __init__(self, pkg_name, alias_name, short_desc, data_manager): ''' init docs ''' IconItem.__init__(self) self.alias_name = alias_name self.pkg_name = pkg_name self.short_desc = short_desc self.data_manager = data_manager self.pkg_icon_pixbuf = None self.pkg_icon_width = 0 self.pkg_icon_height = 0 self.star_level = get_star_level(5.0) self.star_buffer = DscStarBuffer(pkg_name, self) self.grade_star = 0 self.pkg_name_area = PkgName() self.width = 240 self.height = 114 self.button_status = BUTTON_NORMAL ### TODO: is_installed status self.install_status = "uninstalled" self.desktops = [] self.data_manager.get_pkg_installed(self.pkg_name, self.handle_pkg_status) def handle_pkg_status(self, status, success): if success: self.install_status = str(status) try: self.desktops = json.loads(self.install_status) self.desktops = self.data_manager.get_pkg_desktop_info( self.desktops) except: pass self.emit_redraw_request() else: global_logger.error("%s: get_pkg_installed handle_dbus_error" % self.pkg_name) global_logger.error(status) def get_width(self): ''' Get item width. This is IconView interface, you should implement it. ''' return self.width def get_height(self): ''' Get item height. This is IconView interface, you should implement it. ''' return self.height def init_pkg_icon_pixbuf(self): if self.pkg_icon_pixbuf == None: self.pkg_icon_pixbuf = gtk.gdk.pixbuf_new_from_file( get_icon_pixbuf_path(self.pkg_name)) if self.pkg_icon_pixbuf: self.pkg_icon_width = self.pkg_icon_pixbuf.get_width() self.pkg_icon_height = self.pkg_icon_pixbuf.get_height() def render(self, cr, rect): # Draw icon. self.init_pkg_icon_pixbuf() draw_pixbuf( cr, self.pkg_icon_pixbuf, rect.x + self.DRAW_PADDING_LEFT + (ICON_SIZE - self.pkg_icon_width) / 2, rect.y + self.DRAW_PADDING_Y) # Draw button. name = "" draw_str = "" if self.install_status == "uninstalled": name = "button/install_small" elif self.install_status == "unknown": draw_str = _("Not found") else: if self.desktops: name = "button/start_small" else: draw_str = _("Installed") if name: pixbuf = app_theme.get_pixbuf( "%s_%s.png" % (name, button_status_dict[self.button_status])).get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + self.DRAW_PADDING_LEFT, rect.y + self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y) else: str_width, str_height = get_content_size(draw_str, 10) draw_text( cr, draw_str, rect.x + self.DRAW_PADDING_LEFT, rect.y + self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y, rect.width, str_height, wrap_width=rect.width, ) # Draw name. self.text_width = rect.width - self.DRAW_PADDING_LEFT - self.DRAW_PADDING_RIGHT - self.DRAW_INFO_PADDING_X - self.pkg_icon_width self.pkg_name_area.render( cr, self.alias_name, gtk.gdk.Rectangle( rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_PADDING_Y, self.text_width, NAME_SIZE)) # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle( rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_STAR_PADDING_Y, STAR_SIZE * 5, STAR_SIZE)) # Draw long desc. long_desc_height = 32 if self.short_desc == None: self.short_desc = "FIX ME" with cairo_state(cr): cr.rectangle( rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_LONG_DESC_PADDING_Y, self.text_width, long_desc_height, ) cr.clip() draw_text( cr, self.short_desc, rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_LONG_DESC_PADDING_Y, self.text_width, long_desc_height, wrap_width=self.text_width, ) def is_in_star_area(self, x, y): return is_in_rect((x, y), (self.DRAW_PADDING_LEFT + self.pkg_icon_width + self.DRAW_INFO_PADDING_X, self.DRAW_STAR_PADDING_Y, STAR_SIZE * 5, STAR_SIZE)) def is_in_button_area(self, x, y): return is_in_rect((x, y), ( self.DRAW_PADDING_LEFT, self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y, self.BUTTON_WIDTH, self.BUTTON_HEIGHT, )) def is_in_icon_area(self, x, y): self.init_pkg_icon_pixbuf() return is_in_rect((x, y), (self.DRAW_PADDING_LEFT, self.DRAW_PADDING_Y, self.pkg_icon_width, self.pkg_icon_height)) def is_in_name_area(self, x, y): (text_width, text_height) = get_content_size(self.alias_name, text_size=NAME_SIZE) return is_in_rect( (x, y), (self.DRAW_PADDING_LEFT + self.pkg_icon_width + self.DRAW_INFO_PADDING_X, self.DRAW_PADDING_Y, text_width, NAME_SIZE)) def icon_item_motion_notify(self, x, y): ''' Handle `motion-notify-event` signal. This is IconView interface, you should implement it. ''' self.hover_flag = True self.emit_redraw_request() if self.is_in_star_area(x, y): global_event.emit("set-cursor", gtk.gdk.HAND2) offset_x = x - (self.DRAW_PADDING_LEFT + self.pkg_icon_pixbuf.get_width() + self.DRAW_INFO_PADDING_X) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star self.emit_redraw_request() elif self.is_in_icon_area(x, y) or self.is_in_name_area(x, y): global_event.emit("set-cursor", gtk.gdk.HAND2) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level self.emit_redraw_request() if self.is_in_button_area(x, y): self.button_status = BUTTON_HOVER self.emit_redraw_request() elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL self.emit_redraw_request() def get_offset_with_button(self, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/start_normal.png").get_pixbuf() popup_x = self.DRAW_PADDING_LEFT + pixbuf.get_width() / 2 popup_y = self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y return (offset_x, offset_y, popup_x, popup_y) def icon_item_button_press(self, x, y): global timeout_tooltip_action_id ''' Handle button-press event. This is IconView interface, you should implement it. ''' if self.is_in_star_area(x, y): global_event.emit("grade-pkg", (self.pkg_name, self.star_buffer), self.grade_star) elif self.is_in_button_area(x, y): if self.desktops: global_event.emit("start-pkg", self.alias_name, self.desktops, self.get_offset_with_button(x, y)) else: global_event.emit("install-pkg", [self.pkg_name]) self.button_status = BUTTON_PRESS self.emit_redraw_request() elif self.is_in_icon_area(x, y): global_event.emit("switch-to-detail-page", self.pkg_name) elif self.is_in_name_area(x, y): if timeout_tooltip_action_id: gobject.source_remove(timeout_tooltip_action_id) timeout_tooltip_action_id = None global_event.emit('hide-pkg-name-tooltip') global_event.emit("switch-to-detail-page", self.pkg_name) def icon_item_button_release(self, x, y): ''' Handle button-release event. This is IconView interface, you should implement it. ''' if self.is_in_button_area(x, y): self.button_status = BUTTON_HOVER self.emit_redraw_request() elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL self.emit_redraw_request() def icon_item_release_resource(self): ''' Release item resource. If you have pixbuf in item, you should release memory resource like below code: >>> del self.pixbuf >>> self.pixbuf = None 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.pkg_icon_pixbuf: del self.pkg_icon_pixbuf self.pkg_icon_pixbuf = None return True
class PkgIconItem(IconItem): ''' class docs ''' ALIAS_NAME_SIZE = 12 PADDING_X = 10 PADDING_Y = 10 PADDING_MIDDLE = 10 BUTTON_PADDING_X = ITEM_PADDING_X BUTTON_PADDING_Y = 60 BUTTON_WIDTH = 48 BUTTON_HEIGHT = 18 DRAW_ICON_SIZE = 48 DRAW_PADDING_LEFT = 20 DRAW_PADDING_RIGHT = 10 DRAW_PADDING_Y = 16 DRAW_BUTTON_PADDING_Y = 13 DRAW_INFO_PADDING_X = 15 DRAW_STAR_PADDING_Y = 40 DRAW_LONG_DESC_PADDING_Y = 68 def __init__(self, pkg_name, alias_name, short_desc, data_manager): ''' init docs ''' IconItem.__init__(self) self.alias_name = alias_name self.pkg_name = pkg_name self.short_desc = short_desc self.data_manager = data_manager self.pkg_icon_pixbuf = None self.pkg_icon_width = 0 self.pkg_icon_height = 0 self.star_level = get_star_level(5.0) self.star_buffer = DscStarBuffer(pkg_name, self) self.grade_star = 0 self.pkg_name_area = PkgName() self.width = 240 self.height = 114 self.button_status = BUTTON_NORMAL ### TODO: is_installed status self.install_status = "uninstalled" self.desktops = [] self.data_manager.get_pkg_installed(self.pkg_name, self.handle_pkg_status) def handle_pkg_status(self, status, success): if success: self.install_status= str(status) self.emit_redraw_request() else: global_logger.logerror("%s: get_pkg_installed handle_dbus_error" % self.pkg_name) global_logger.logerror(status) def get_width(self): ''' Get item width. This is IconView interface, you should implement it. ''' return self.width def get_height(self): ''' Get item height. This is IconView interface, you should implement it. ''' return self.height def init_pkg_icon_pixbuf(self): if self.pkg_icon_pixbuf == None: self.pkg_icon_pixbuf = gtk.gdk.pixbuf_new_from_file(get_icon_pixbuf_path(self.pkg_name)) if self.pkg_icon_pixbuf: self.pkg_icon_width = self.pkg_icon_pixbuf.get_width() self.pkg_icon_height = self.pkg_icon_pixbuf.get_height() def render(self, cr, rect): # Draw icon. self.init_pkg_icon_pixbuf() draw_pixbuf( cr, self.pkg_icon_pixbuf, rect.x + self.DRAW_PADDING_LEFT + (ICON_SIZE - self.pkg_icon_width) / 2, rect.y + self.DRAW_PADDING_Y) # Draw button. name = "" draw_str = "" if self.install_status == "uninstalled": name = "button/install_small" elif self.install_status == "unknown": draw_str = _("Not found") else: desktops = json.loads(self.install_status) if desktops: name = "button/start_small" self.desktops = self.data_manager.get_pkg_desktop_info(desktops) else: draw_str = _("Installed") if name: if self.button_status == BUTTON_NORMAL: status = "normal" elif self.button_status == BUTTON_HOVER: status = "hover" elif self.button_status == BUTTON_PRESS: status = "press" pixbuf = app_theme.get_pixbuf("%s_%s.png" % (name, status)).get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + self.DRAW_PADDING_LEFT, rect.y + self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y) else: str_width, str_height = get_content_size(draw_str, 10) draw_text( cr, draw_str, rect.x + self.DRAW_PADDING_LEFT, rect.y + self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y, rect.width, str_height, wrap_width=rect.width, ) # Draw name. self.text_width = rect.width - self.DRAW_PADDING_LEFT - self.DRAW_PADDING_RIGHT - self.DRAW_INFO_PADDING_X - self.pkg_icon_width self.pkg_name_area.render( cr, self.alias_name, gtk.gdk.Rectangle( rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_PADDING_Y, self.text_width, NAME_SIZE)) # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle( rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_STAR_PADDING_Y, STAR_SIZE * 5, STAR_SIZE )) # Draw long desc. long_desc_height = 32 if self.short_desc == None: self.short_desc = "FIX ME" with cairo_state(cr): cr.rectangle( rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_LONG_DESC_PADDING_Y, self.text_width, long_desc_height, ) cr.clip() draw_text( cr, self.short_desc, rect.x + self.DRAW_PADDING_LEFT + ICON_SIZE + self.DRAW_INFO_PADDING_X, rect.y + self.DRAW_LONG_DESC_PADDING_Y, self.text_width, long_desc_height, wrap_width=self.text_width, ) def is_in_star_area(self, x, y): return is_in_rect((x, y), (self.DRAW_PADDING_LEFT + self.pkg_icon_width + self.DRAW_INFO_PADDING_X, self.DRAW_STAR_PADDING_Y, STAR_SIZE * 5, STAR_SIZE )) def is_in_button_area(self, x, y): return is_in_rect((x, y), (self.DRAW_PADDING_LEFT, self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y, self.BUTTON_WIDTH, self.BUTTON_HEIGHT, )) def is_in_icon_area(self, x, y): self.init_pkg_icon_pixbuf() return is_in_rect((x, y), (self.DRAW_PADDING_LEFT, self.DRAW_PADDING_Y, self.pkg_icon_width, self.pkg_icon_height)) def is_in_name_area(self, x, y): (text_width, text_height) = get_content_size(self.alias_name, text_size=NAME_SIZE) return is_in_rect((x, y), (self.DRAW_PADDING_LEFT + self.pkg_icon_width + self.DRAW_INFO_PADDING_X, self.DRAW_PADDING_Y, text_width, NAME_SIZE)) def icon_item_motion_notify(self, x, y): ''' Handle `motion-notify-event` signal. This is IconView interface, you should implement it. ''' self.hover_flag = True self.emit_redraw_request() if self.is_in_star_area(x, y): global_event.emit("set-cursor", gtk.gdk.HAND2) offset_x = x - (self.DRAW_PADDING_LEFT + self.pkg_icon_pixbuf.get_width() + self.DRAW_INFO_PADDING_X) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star self.emit_redraw_request() elif self.is_in_icon_area(x, y) or self.is_in_name_area(x, y): global_event.emit("set-cursor", gtk.gdk.HAND2) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level self.emit_redraw_request() if self.is_in_button_area(x, y): self.button_status = BUTTON_HOVER self.emit_redraw_request() elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL self.emit_redraw_request() def get_offset_with_button(self, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/start_normal.png").get_pixbuf() popup_x = self.DRAW_PADDING_LEFT + pixbuf.get_width() / 2 popup_y = self.DRAW_PADDING_Y + self.DRAW_ICON_SIZE + self.DRAW_BUTTON_PADDING_Y return (offset_x, offset_y, popup_x, popup_y) def icon_item_button_press(self, x, y): global timeout_tooltip_action_id ''' Handle button-press event. This is IconView interface, you should implement it. ''' if self.is_in_star_area(x, y): global_event.emit("grade-pkg", (self.pkg_name, self.star_buffer), self.grade_star) elif self.is_in_button_area(x, y): if self.desktops: global_event.emit("start-pkg", self.alias_name, self.desktops, self.get_offset_with_button(x, y)) else: global_event.emit("install-pkg", [self.pkg_name]) self.button_status = BUTTON_PRESS self.emit_redraw_request() elif self.is_in_icon_area(x, y): global_event.emit("switch-to-detail-page", self.pkg_name) elif self.is_in_name_area(x, y): if timeout_tooltip_action_id: gobject.source_remove(timeout_tooltip_action_id) timeout_tooltip_action_id = None global_event.emit('hide-pkg-name-tooltip') global_event.emit("switch-to-detail-page", self.pkg_name) def icon_item_button_release(self, x, y): ''' Handle button-release event. This is IconView interface, you should implement it. ''' if self.is_in_button_area(x, y): self.button_status = BUTTON_HOVER self.emit_redraw_request() elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL self.emit_redraw_request() def icon_item_release_resource(self): ''' Release item resource. If you have pixbuf in item, you should release memory resource like below code: >>> del self.pixbuf >>> self.pixbuf = None 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.pkg_icon_pixbuf: del self.pkg_icon_pixbuf self.pkg_icon_pixbuf = None return True
class SearchItem(TreeItem): ''' class docs ''' def __init__(self, pkg_name, data_manager, keywords): ''' init docs ''' TreeItem.__init__(self) self.pkg_name = pkg_name self.data_manager = data_manager self.keywords = keywords self.icon_pixbuf = None (self.alias_name, self.short_desc, self.long_desc, star) = data_manager.get_pkg_search_info(self.pkg_name) info = self.data_manager.get_item_pkg_info(self.pkg_name) self.alias_name = info[1] self.short_desc = info[2] self.long_desc = info[3] self.star_level = get_star_level(5.0) self.star_buffer = DscStarBuffer(pkg_name) self.grade_star = 0 self.highlight_string = get_match_context('\n'.join([self.short_desc, self.long_desc]), self.keywords) self.button_status = BUTTON_NORMAL ### TODO: is_installed status self.install_status = "uninstalled" self.desktops = [] self.data_manager.get_pkg_installed(self.pkg_name, self.handle_pkg_status) def handle_pkg_status(self, status, success): if success: self.install_status= str(status) if self.install_status == "unknown": global_event.emit("delete-search-page-items", [self]) else: try: self.desktops = json.loads(self.install_status) self.desktops = self.data_manager.get_pkg_desktop_info(self.desktops) except: pass self.emit_redraw_request() else: utils.global_logger.error("%s: get_pkg_installed handle_dbus_error" % self.pkg_name) utils.global_logger.error(status) def render_info(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() # Render icon. if self.icon_pixbuf == None: self.icon_pixbuf = gtk.gdk.pixbuf_new_from_file( get_icon_pixbuf_path(utils.get_origin_name(self.pkg_name))) render_pkg_icon(cr, rect, self.icon_pixbuf) # Render name. render_pkg_name(cr, rect, get_match_context(self.alias_name, self.keywords), rect.width) # Render search result. with cairo_state(cr): text_padding_left = ITEM_PADDING_X + ICON_SIZE + ITEM_PADDING_MIDDLE text_padding_right = 10 text_padding_y = ITEM_PADDING_Y + DEFAULT_FONT_SIZE * 2 text_width = rect.width - text_padding_left - text_padding_right text_height = 30 cr.rectangle(rect.x, rect.y + text_padding_y, rect.width, text_height) cr.clip() draw_text( cr, self.highlight_string, rect.x + text_padding_left, rect.y + text_padding_y, text_width, text_height, text_size=DEFAULT_FONT_SIZE, wrap_width=text_width, ) def render_pkg_status(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() # Render star. self.star_buffer.render(cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) # Draw button. name = "" draw_str = "" if self.install_status == "uninstalled": name = "button/install_small" elif self.install_status == "unknown": draw_str = _("Not found") else: if self.desktops: name = "button/start_small" else: draw_str = _("Installed") # Render button. if name: if self.button_status == BUTTON_NORMAL: status = "normal" elif self.button_status == BUTTON_HOVER: status = "hover" elif self.button_status == BUTTON_PRESS: status = "press" pixbuf = app_theme.get_pixbuf("%s_%s.png" % (name, status)).get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), rect.y + (rect.height - pixbuf.get_height()) / 2 ) else: str_width, str_height = get_content_size(draw_str, 10) draw_text( cr, draw_str, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - str_width, rect.y + (rect.height - str_height) / 2, rect.width, str_height, wrap_width=rect.width ) def is_in_button_area(self, column, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/start_normal.png").get_pixbuf() return (column == 1 and is_in_rect((offset_x, offset_y), (self.get_column_widths()[column] - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), (ITEM_HEIGHT - pixbuf.get_height()) / 2, pixbuf.get_width(), pixbuf.get_height() ))) def is_in_star_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect((offset_x, offset_y), (0, (ITEM_HEIGHT - STAR_SIZE) / 2, ITEM_STAR_AREA_WIDTH, STAR_SIZE))) def is_in_icon_area(self, column, offset_x, offset_y): return (column == 0 and is_in_rect((offset_x, offset_y), (ITEM_PADDING_X, ITEM_PADDING_Y, self.icon_pixbuf.get_width(), self.icon_pixbuf.get_height() ))) def is_in_name_area(self, column, offset_x, offset_y): (name_width, name_height) = get_content_size(self.alias_name, NAME_SIZE) return (column == 0 and is_in_rect((offset_x, offset_y), (ITEM_PADDING_X + ICON_SIZE + ITEM_PADDING_MIDDLE, ITEM_PADDING_Y, name_width, name_height, ))) def get_height(self): return ITEM_HEIGHT def get_column_widths(self): return [ITEM_INFO_AREA_WIDTH, ITEM_STAR_AREA_WIDTH + ITEM_BUTTON_AREA_WIDTH] def get_column_renders(self): return [self.render_info, self.render_pkg_status] def unselect(self): pass def select(self): pass def unhover(self, column, offset_x, offset_y): pass def hover(self, column, offset_x, offset_y): pass def motion_notify(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y) or self.is_in_name_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) else: global_event.emit("set-cursor", None) else: if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star if self.redraw_request_callback: self.redraw_request_callback(self) else: if self.desktops: if self.is_in_button_area(column, offset_x, offset_y): self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self, True) else: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self, True) global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level if self.redraw_request_callback: self.redraw_request_callback(self) def get_offset_with_button(self, offset_x, offset_y): pixbuf = app_theme.get_pixbuf("button/start_normal.png").get_pixbuf() popup_x = self.get_column_widths()[1] - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width() / 2 popup_y = (ITEM_HEIGHT - pixbuf.get_height()) / 2 return (offset_x, offset_y, popup_x, popup_y) def button_press(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y) or self.is_in_name_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) else: if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("grade-pkg", self.pkg_name, self.grade_star) elif self.is_in_button_area(column, offset_x, offset_y): if self.desktops: global_event.emit("start-pkg", self.alias_name, self.desktops, self.get_offset_with_button(offset_x, offset_y)) self.button_status = BUTTON_PRESS if self.redraw_request_callback: self.redraw_request_callback(self, True) else: global_event.emit("install-pkg", [self.pkg_name]) self.button_status = BUTTON_PRESS if self.redraw_request_callback: self.redraw_request_callback(self, True) else: global_event.emit("switch-to-detail-page", self.pkg_name) def button_release(self, column, offset_x, offset_y): if self.desktops: if self.is_in_button_area(column, offset_x, offset_y): if self.button_status != BUTTON_HOVER: self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self, True) else: if self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self, True) def single_click(self, column, offset_x, offset_y): pass def double_click(self, column, offset_x, offset_y): pass def 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 TreeView interface, you should implement it. @return: Return True if do release work, otherwise return False. When this function return True, TreeView will call function gc.collect() to release object to release memory. ''' if self.icon_pixbuf: del self.icon_pixbuf self.icon_pixbuf = None return True
class UninstallItem(TreeItem): ''' class docs ''' STATUS_NORMAL = 1 STATUS_CONFIRM = 2 STATUS_WAIT_ACTION = 3 STATUS_IN_ACTION = 4 STATUS_PADDING_X = 15 def __init__(self, pkg_name, pkg_version, data_manager): ''' init docs ''' TreeItem.__init__(self) self.pkg_name = pkg_name self.pkg_version = pkg_version self.data_manager = data_manager self.icon_pixbuf = None info = data_manager.get_item_pkg_info(self.pkg_name) self.alias_name = info[1] self.short_desc = info[2] self.star_level = get_star_level(5.0) self.star_buffer = DscStarBuffer(pkg_name) self.grade_star = 0 button_pixbuf = app_theme.get_pixbuf( "button/uninstall_normal.png").get_pixbuf() (self.button_width, self.button_height ) = button_pixbuf.get_width(), button_pixbuf.get_height() self.button_status = BUTTON_NORMAL self.status = self.STATUS_NORMAL self.status_text = "" self.progress_buffer = ProgressBuffer() #self.action_wait() def render_pkg_info(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.icon_pixbuf == None: self.icon_pixbuf = gtk.gdk.pixbuf_new_from_file( get_icon_pixbuf_path(self.pkg_name)) render_pkg_info(cr, rect, self.alias_name, self.pkg_name, self.icon_pixbuf, self.pkg_version, self.short_desc, ITEM_PKG_OFFSET_X) def render_pkg_status(self, cr, rect): if self.row_index % 2 == 1: cr.set_source_rgba(1, 1, 1, 0.5) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() if self.status == self.STATUS_CONFIRM: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) confirm_pixbuf = app_theme.get_pixbuf( "button/uninstall_confirm.png").get_pixbuf() cancel_pixbuf = app_theme.get_pixbuf( "button/uninstall_cancel.png").get_pixbuf() draw_pixbuf( cr, confirm_pixbuf, rect.x + rect.width - ITEM_CONFIRM_BUTTON_PADDING_RIGHT, rect.y + (ITEM_HEIGHT - confirm_pixbuf.get_height()) / 2, ) draw_pixbuf( cr, cancel_pixbuf, rect.x + rect.width - ITEM_CANCEL_BUTTON_PADDING_RIGHT, rect.y + (ITEM_HEIGHT - cancel_pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_IN_ACTION: self.progress_buffer.render( cr, gtk.gdk.Rectangle( rect.x, rect.y + (ITEM_HEIGHT - PROGRESSBAR_HEIGHT) / 2, ITEM_STAR_AREA_WIDTH, PROGRESSBAR_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT, ) elif self.status == self.STATUS_WAIT_ACTION: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) draw_text( cr, self.status_text, rect.x + rect.width - ITEM_STATUS_TEXT_PADDING_RIGHT, rect.y, rect.width - ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT, ) cancel_pixbuf = app_theme.get_pixbuf( "button/uninstall_cancel.png").get_pixbuf() draw_pixbuf( cr, cancel_pixbuf, rect.x + rect.width - 50, rect.y + (ITEM_HEIGHT - cancel_pixbuf.get_height()) / 2, ) elif self.status == self.STATUS_NORMAL: # Draw star. self.star_buffer.render( cr, gtk.gdk.Rectangle(rect.x, rect.y, ITEM_STAR_AREA_WIDTH, ITEM_HEIGHT)) # Draw button. if self.button_status == BUTTON_NORMAL: pixbuf = app_theme.get_pixbuf( "button/uninstall_normal.png").get_pixbuf() elif self.button_status == BUTTON_HOVER: pixbuf = app_theme.get_pixbuf( "button/uninstall_hover.png").get_pixbuf() elif self.button_status == BUTTON_PRESS: pixbuf = app_theme.get_pixbuf( "button/uninstall_press.png").get_pixbuf() draw_pixbuf( cr, pixbuf, rect.x + rect.width - ITEM_BUTTON_PADDING_RIGHT - pixbuf.get_width(), rect.y + (ITEM_HEIGHT - self.button_height) / 2, ) def get_height(self): return ITEM_HEIGHT def get_column_widths(self): return [ ITEM_INFO_AREA_WIDTH, ITEM_STAR_AREA_WIDTH + ITEM_BUTTON_AREA_WIDTH ] def get_column_renders(self): return [self.render_pkg_info, self.render_pkg_status] def unselect(self): pass def select(self): pass def unhover(self, column, offset_x, offset_y): pass def hover(self, column, offset_x, offset_y): pass def motion_notify(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) else: global_event.emit("set-cursor", None) else: if self.status == self.STATUS_NORMAL: if self.is_in_button_area(column, offset_x, offset_y): self.button_status = BUTTON_HOVER if self.redraw_request_callback: self.redraw_request_callback(self) elif self.button_status != BUTTON_NORMAL: self.button_status = BUTTON_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) if self.is_in_star_area(column, offset_x, offset_y): global_event.emit("set-cursor", gtk.gdk.HAND2) times = offset_x / STAR_SIZE self.grade_star = times * 2 + 2 self.grade_star = min(self.grade_star, 10) self.star_buffer.star_level = self.grade_star if self.redraw_request_callback: self.redraw_request_callback(self) else: global_event.emit("set-cursor", None) if self.star_buffer.star_level != self.star_level: self.star_buffer.star_level = self.star_level if self.redraw_request_callback: self.redraw_request_callback(self) def button_press(self, column, offset_x, offset_y): if column == 0: if self.is_in_icon_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) elif self.is_in_name_area(column, offset_x, offset_y): global_event.emit("switch-to-detail-page", self.pkg_name) global_event.emit("set-cursor", None) else: if self.status == self.STATUS_NORMAL: if self.is_in_button_area(column, offset_x, offset_y): self.status = self.STATUS_CONFIRM if self.redraw_request_callback: self.redraw_request_callback(self) elif self.is_in_star_area(column, offset_x, offset_y): global_event.emit("grade-pkg", self.pkg_name, self.grade_star) elif self.status == self.STATUS_CONFIRM: if self.is_confirm_button_area(column, offset_x, offset_y): self.status = self.STATUS_WAIT_ACTION self.status_text = _("Waiting for uninstall") if self.redraw_request_callback: self.redraw_request_callback(self) global_event.emit("uninstall-pkg", self.pkg_name, get_purg_flag()) elif self.is_cancel_button_area(column, offset_x, offset_y): self.status = self.STATUS_NORMAL if self.redraw_request_callback: self.redraw_request_callback(self) elif self.status == self.STATUS_WAIT_ACTION: if self.is_cancel_button_area(column, offset_x, offset_y): self.status = self.STATUS_NORMAL global_event.emit("remove-wait-action", [(self.pkg_name, ACTION_UNINSTALL)]) if self.redraw_request_callback: self.redraw_request_callback(self) def button_release(self, column, offset_x, offset_y): pass def single_click(self, column, offset_x, offset_y): pass def double_click(self, column, offset_x, offset_y): pass def is_in_star_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect( (offset_x, offset_y), (0, (ITEM_HEIGHT - STAR_SIZE) / 2, ITEM_STAR_AREA_WIDTH, STAR_SIZE))) def is_in_button_area(self, column, offset_x, offset_y): return (column == 1 and is_in_rect( (offset_x, offset_y), (self.get_column_widths()[column] - ITEM_BUTTON_PADDING_RIGHT - self.button_width, (ITEM_HEIGHT - self.button_height) / 2, self.button_width, self.button_height))) def is_confirm_button_area(self, column, offset_x, offset_y): confirm_pixbuf = app_theme.get_pixbuf( "button/uninstall_confirm.png").get_pixbuf() return (column == 1 and is_in_rect( (offset_x, offset_y), (self.get_column_widths()[column] - ITEM_CONFIRM_BUTTON_PADDING_RIGHT, (ITEM_HEIGHT - confirm_pixbuf.get_height()) / 2, confirm_pixbuf.get_width(), confirm_pixbuf.get_height()))) def is_cancel_button_area(self, column, offset_x, offset_y): cancel_pixbuf = app_theme.get_pixbuf( "button/uninstall_cancel.png").get_pixbuf() return (column == 1 and is_in_rect( (offset_x, offset_y), (self.get_column_widths()[column] - ITEM_CANCEL_BUTTON_PADDING_RIGHT, (ITEM_HEIGHT - cancel_pixbuf.get_height()) / 2, cancel_pixbuf.get_width(), cancel_pixbuf.get_height()))) def is_in_name_area(self, column, offset_x, offset_y): (name_width, name_height) = get_content_size(self.alias_name, NAME_SIZE) return (column == 0 and is_in_rect( (offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X + ICON_SIZE + ITEM_PADDING_MIDDLE, ITEM_PADDING_Y, name_width, NAME_SIZE))) def is_in_icon_area(self, column, offset_x, offset_y): return (column == 0 and self.icon_pixbuf != None and is_in_rect( (offset_x, offset_y), (ITEM_PADDING_X + ITEM_PKG_OFFSET_X, ITEM_PADDING_Y, self.icon_pixbuf.get_width(), self.icon_pixbuf.get_height()))) def action_wait(self): self.status = self.STATUS_WAIT_ACTION self.status_text = _("Waiting for uninstall") if self.redraw_request_callback: self.redraw_request_callback(self) def action_start(self): self.status = self.STATUS_IN_ACTION self.status_text = _("Uninstalling") if self.redraw_request_callback: self.redraw_request_callback(self) def action_update(self, percent): self.progress_buffer.progress = percent self.status_text = _("Uninstalling") if self.redraw_request_callback: self.redraw_request_callback(self) def action_finish(self): self.progress_buffer.progress = 100 self.status_text = _("Uninstallation completed") if self.redraw_request_callback: self.redraw_request_callback(self) def 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 TreeView interface, you should implement it. @return: Return True if do release work, otherwise return False. When this function return True, TreeView will call function gc.collect() to release object to release memory. ''' if self.icon_pixbuf: del self.icon_pixbuf self.icon_pixbuf = None return True