def _setup_not_found_box(self, search_text): """ Setup "not found" message label and layout """ nf_box = self._not_found_box with self._entropy.rwsem().reader(): # now self._not_found_label is available meant_packages = self._entropy.get_meant_packages(search_text) text = escape_markup(search_text) msg = "%s <b>%s</b>" % ( escape_markup(_("Nothing found for")), text, ) if meant_packages: first_entry = meant_packages[0] app = Application(self._entropy, self._entropy_ws, self._service, first_entry) name = app.name msg += ", %s" % ( prepare_markup(_("did you mean <a href=\"%s\">%s</a>?")) % ( escape_markup(name), escape_markup(name), ), ) self._not_found_label.set_markup(msg)
def _render_comment_header(self, *args): """ Render the comment header label. This method can be called multiple times (to show/hide the remove link). """ logged_username = None if self._webserv is not None: logged_username = self._webserv.get_credentials() ts_id = Document.DOCUMENT_TIMESTAMP_ID doc_username_id = DocumentFactory.DOCUMENT_USERNAME_ID doc_username = self._comment[doc_username_id] time_str = entropy.tools.convert_unix_time_to_human_time( self._comment[ts_id]) time_str = escape_markup(time_str) remove_str = "" if logged_username == doc_username: remove_str = ", <b><a href=\"remove\">%s</a></b>" % ( escape_markup(_("remove")),) self._header_label.set_markup( "<small><b>%s</b>" % (escape_markup(doc_username),) \ + ", <i>" + time_str + "</i>" + remove_str \ + "</small>") self._header_label.set_line_wrap(True) self._header_label.set_line_wrap_mode(Pango.WrapMode.WORD) self._header_label.set_alignment(0.0, 1.0) self._header_label.set_name("comment-box-author")
def _setup_not_found_box(self, search_text): """ Setup "not found" message label and layout """ nf_box = self._not_found_box with self._entropy.rwsem().reader(): # now self._not_found_label is available meant_packages = self._entropy.get_meant_packages( search_text) text = escape_markup(search_text) msg = "%s <b>%s</b>" % ( escape_markup(_("Nothing found for")), text,) if meant_packages: first_entry = meant_packages[0] app = Application( self._entropy, self._entropy_ws, self._service, first_entry) name = app.name msg += ", %s" % ( prepare_markup(_("did you mean <a href=\"%s\">%s</a>?")) % ( escape_markup(name), escape_markup(name),),) self._not_found_label.set_markup(msg)
def _setup_terminal_menu(self): """ Setup TerminalWidget Right Click popup-menu. """ self._terminal_menu = Gtk.Menu() sall_menu_item = Gtk.ImageMenuItem.new_from_stock( "gtk-select-all", None) sall_menu_item.connect("activate", self._on_terminal_select_all) self._terminal_menu.append(sall_menu_item) copy_menu_item = Gtk.ImageMenuItem.new_from_stock( "gtk-copy", None) copy_menu_item.connect("activate", self._on_terminal_copy) self._terminal_menu.append(copy_menu_item) reset_menu_item = Gtk.ImageMenuItem.new_from_stock( "gtk-clear", None) reset_menu_item.connect("activate", self._on_terminal_reset) self._terminal_menu.append(reset_menu_item) black_menu_item = Gtk.ImageMenuItem.new_with_label( escape_markup(_("Black on White"))) black_menu_item.connect("activate", self._on_terminal_color, True) self._terminal_menu.append(black_menu_item) white_menu_item = Gtk.ImageMenuItem.new_with_label( escape_markup(_("White on Black"))) white_menu_item.connect("activate", self._on_terminal_color, False) self._terminal_menu.append(white_menu_item) self._terminal_menu.show_all()
def get_markup(self): """ Return ConfigurationUpdate markup text. """ msg = "<b>%s</b>\n<small><b>%s</b>, " + \ "<i>%s</i>\n<u>%s</u></small>" msg = msg % (escape_markup( self.title()), escape_markup(self.repository()), escape_markup(self.date()), escape_markup(self.link())) return prepare_markup(msg)
def get_markup(self): """ Return Repository markup text. """ msg = "<b>%s</b>\n<small><i>%s</i>\n<b>%s</b></small>" if self.enabled(): enabled_msg = _("Enabled") else: enabled_msg = _("Disabled") msg = msg % (escape_markup(self.repository()), escape_markup(self.description()), escape_markup(enabled_msg)) return prepare_markup(msg)
def get_markup(self): """ Return ConfigurationUpdate markup text. """ msg = "<b>%s</b>\n<small><b>%s</b>, " + \ "<i>%s</i>\n<u>%s</u></small>" msg = msg % ( escape_markup(self.title()), escape_markup(self.repository()), escape_markup(self.date()), escape_markup(self.link())) return prepare_markup(msg)
def render(self): """ Setup the CommentBox content. Shall be called once. """ vbox = Gtk.VBox() self._render_comment_header() self._header_label.connect( "activate-link", self._on_activate_link) vbox.pack_start(self._header_label, False, False, 0) # title, keywords, ddata, document_id title = self._comment['title'].strip() if title: title_id = Document.DOCUMENT_TITLE_ID label = Gtk.Label() label_align = Gtk.Alignment() label_align.set_padding(0, 3, 0, 0) label_align.add(label) label.set_markup( "<b>" + escape_markup(self._comment[title_id]) + "</b>") label.set_name("comment-box-title") label.set_line_wrap(True) label.set_line_wrap_mode(Pango.WrapMode.WORD) label.set_alignment(0.0, 0.0) label.set_selectable(True) vbox.pack_start(label_align, False, False, 0) data_id = Document.DOCUMENT_DATA_ID label = Gtk.Label() label_align = Gtk.Alignment() label_align.set_padding(0, 15, 0, 0) label_align.add(label) label.set_markup( "<small>" + \ escape_markup(self._comment[data_id]) + "</small>") label.set_name("comment-box-comment") label.set_line_wrap(True) label.set_line_wrap_mode(Pango.WrapMode.WORD) label.set_alignment(0.0, 0.0) label.set_selectable(True) vbox.pack_start(label_align, False, False, 0) self.pack_start(vbox, False, False, 0) self._avc.connect("logged-in", self._render_comment_header) self._avc.connect("logged-out", self._render_comment_header) vbox.show_all()
def _setup_application_info(self, app, metadata): """ Setup the actual UI widgets content and emit 'application-show' """ self._setup_application_markup(metadata["markup"]) self._app_info_lbl.set_markup(metadata["info"]) # install/remove/update buttons self._setup_buttons(app, metadata["is_installed"], metadata["is_updatable"]) # only comments supported, point to the remote # www service for the rest if app.is_installed_app(): self._app_comment_more_label.hide() else: self._app_comment_more_label.set_markup( '<b>%s</b>: <a href="%s">%s</a>' % ( escape_markup(_("Want to add images, etc?")), escape_markup(build_application_store_url(app, "ugc")), escape_markup(_("click here!")), ) ) self._app_comment_more_label.show() stats = metadata["stats"] icon = metadata["icon"] self._setup_application_stats(stats, icon) # load application comments asynchronously # so at the beginning, just place a spinner spinner = Gtk.Spinner() spinner.set_size_request(-1, 48) spinner.set_tooltip_text(escape_markup(_("Loading comments..."))) spinner.set_name("comment-box-spinner") for child in self._app_comments_box.get_children(): child.destroy() self._app_comments_box.pack_start(spinner, False, False, 0) spinner.show() spinner.start() downloader = ApplicationViewController.MetadataDownloader( app, self, self._append_comments_safe, app.download_comments ) downloader.start() downloader = ApplicationViewController.MetadataDownloader( app, self, self._append_images_safe, app.download_images ) downloader.start() self.emit("application-show", app)
def get_markup(self): """ Return Repository markup text. """ msg = "<b>%s</b>\n<small><i>%s</i>\n<b>%s</b></small>" if self.enabled(): enabled_msg = _("Enabled") else: enabled_msg = _("Disabled") msg = msg % (escape_markup( self.repository()), escape_markup( self.description()), escape_markup(enabled_msg)) return prepare_markup(msg)
def _setup_application_info(self, app, metadata): """ Setup the actual UI widgets content and emit 'application-show' """ self._setup_application_markup(metadata['markup']) self._app_info_lbl.set_markup(metadata['info']) # install/remove/update buttons self._setup_buttons(app, metadata['is_installed'], metadata['is_updatable']) # only comments supported, point to the remote # www service for the rest if app.is_installed_app(): self._app_comment_more_label.hide() else: self._app_comment_more_label.set_markup( "<b>%s</b>: <a href=\"%s\">%s</a>" % ( escape_markup(_("Want to add images, etc?")), escape_markup(build_application_store_url(app, "ugc")), escape_markup(_("click here!")), )) self._app_comment_more_label.show() stats = metadata['stats'] icon = metadata['icon'] self._setup_application_stats(stats, icon) # load application comments asynchronously # so at the beginning, just place a spinner spinner = Gtk.Spinner() spinner.set_size_request(-1, 48) spinner.set_tooltip_text(escape_markup(_("Loading comments..."))) spinner.set_name("comment-box-spinner") for child in self._app_comments_box.get_children(): child.destroy() self._app_comments_box.pack_start(spinner, False, False, 0) spinner.show() spinner.start() downloader = ApplicationViewController.MetadataDownloader( app, self, self._append_comments_safe, app.download_comments) downloader.start() downloader = ApplicationViewController.MetadataDownloader( app, self, self._append_images_safe, app.download_images) downloader.start() self.emit("application-show", app)
def _on_work_interrupt(self, widget): """ We've been explicitly asked to interrupt the currently ongoing work """ rc = self._show_yesno_dialog( self._window, escape_markup(_("Activity Interruption")), escape_markup( _("Are you sure you want to interrupt" " the ongoing Activity? The interruption will" " occur as soon as possible, potentially not" " immediately."))) if rc == Gtk.ResponseType.NO: return self._service.interrupt_activity()
def _make_rename_box(self): vbox = Gtk.VBox() hbox = Gtk.HBox() repo_box = Gtk.VBox() repo_label = Gtk.Label() repo_label.set_markup(escape_markup(_("Repository name"))) repo_label.set_alignment(0.0, 0.50) repo_label.set_padding(-1, 5) repo_box.pack_start(repo_label, False, False, 0) self._repo_entry = Gtk.Entry() self._repo_entry.set_text(self._repo.repository()) repo_box.pack_start(self._repo_entry, False, False, 0) hbox.pack_start(repo_box, False, False, 0) hbox.set_property("expand", True) self._repo_message = Gtk.Label() self._repo_message.set_no_show_all(True) self._repo_message.set_alignment(0.0, 1.0) self._repo_message.set_padding(10, 5) self._repo_message.set_name("message-area-error") hbox.pack_start(self._repo_message, False, False, 0) vbox.pack_start(hbox, False, False, 0) return vbox
def update_queue_information(self, queue_len): """ Update Action Queue related info. """ daemon_action = self._last_daemon_action msg = None if daemon_action == DaemonAppActions.INSTALL: msg = _("Installing") elif daemon_action == DaemonAppActions.REMOVE: msg = _("Removing") if msg is not None: more_msg = "" queue_len -= 1 queue_len = max(0, queue_len) if queue_len: more_msg = ngettext(", and <b>%d</b> <i>more in queue</i>", ", and <b>%d</b> <i>more in queue</i>", queue_len) more_msg = prepare_markup(more_msg % (queue_len, )) self._action_label.set_markup("<big><b>%s</b>%s</big>" % ( escape_markup(msg), more_msg, ))
def get_markup(self): """ Return ConfigurationUpdate markup text. """ source = escape_markup(self.root() + self.source()) dest = escape_markup(self.root() + self.destination()) apps = self.apps() msg = "<b>%s</b>\n<small><u>%s</u>: <i>%s</i></small>" % ( source, _("Destination"), dest) if apps: apps_msg = "\n<small><u>%s</u>: %s</small>" % ( _("Applications"), ", ".join(["<i>" + x.name + "</i>" for x in apps]),) msg += apps_msg return prepare_markup(msg)
def _notify_vote_submit(self, app, username, vote): """ Notify User about Comment submission with current credentials. """ msg = ngettext("Rate <b>%s</b> as <b>%s</b>, with <b>%d</b> star?", "Rate <b>%s</b> as <b>%s</b>, with <b>%d</b> stars?", vote) msg = msg % ( app.name, escape_markup(username), vote, ) box = NotificationBox(msg, message_type=Gtk.MessageType.INFO, context_id=self.VOTE_NOTIFICATION_CONTEXT_ID) def _vote_submit(widget): self._vote_submit(app, username, vote) box.add_button(_("_Ok, cool!"), _vote_submit) def _send_vote(): self._on_stars_clicked(self._stars, app=app) def _logout_webservice(widget): self._logout_webservice(app, _send_vote) box.add_button(_("_No, logout!"), _logout_webservice) box.add_destroy_button(_("_Later")) self._nc.append(box)
def update_queue_information(self, queue_len): """ Update Action Queue related info. """ daemon_action = self._last_daemon_action msg = None if daemon_action == DaemonAppActions.INSTALL: msg = _("Installing") elif daemon_action == DaemonAppActions.REMOVE: msg = _("Removing") if msg is not None: more_msg = "" queue_len -= 1 queue_len = max(0, queue_len) if queue_len: more_msg = ngettext( ", and <b>%d</b> <i>more in queue</i>", ", and <b>%d</b> <i>more in queue</i>", queue_len) more_msg = prepare_markup(more_msg % (queue_len,)) self._action_label.set_markup( "<big><b>%s</b>%s</big>" % ( escape_markup(msg), more_msg,))
def _notify_comment_submit(self, app, username, text): """ Notify User about Comment submission with current credentials. """ box = NotificationBox( _("You are about to add a <b>comment</b> as <b>%s</b>.") % (escape_markup(username),), message_type=Gtk.MessageType.INFO, context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID, ) def _comment_submit(widget): self._comment_submit(app, username, text) box.add_button(_("_Ok, cool!"), _comment_submit) def _send_comment(): self._on_send_comment(None, app=app) def _logout_webservice(widget): self._logout_webservice(app, _send_comment) box.add_button(_("_No, logout!"), _logout_webservice) box.add_destroy_button(_("_Later")) self._nc.append(box)
def _notify_comment_submit(self, app, username, text): """ Notify User about Comment submission with current credentials. """ box = NotificationBox( _("You are about to add a <b>comment</b> as <b>%s</b>.") \ % (escape_markup(username),), message_type=Gtk.MessageType.INFO, context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID) def _comment_submit(widget): self._comment_submit(app, username, text) box.add_button(_("_Ok, cool!"), _comment_submit) def _send_comment(): self._on_send_comment(None, app=app) def _logout_webservice(widget): self._logout_webservice(app, _send_comment) box.add_button(_("_No, logout!"), _logout_webservice) box.add_destroy_button(_("_Later")) self._nc.append(box)
def _change_view_state(self, state, lock=False, _ignore_lock=False, payload=None): """ Change Rigo Application UI state. You can pass a custom widget that will be shown in case of static view state. """ with self._state_mutex: if self._current_state_lock and not _ignore_lock: const_debug_write( __name__, "cannot change view state, UI locked") return False txc = self._state_transitions.get(state) if txc is None: raise AttributeError("wrong view state") enter_st, exit_st = txc current_enter_st, current_exit_st = \ self._state_transitions.get( self._current_state) # exit from current state current_exit_st() # enter the new state enter_st() self._current_state = state if lock: self._current_state_lock = True state_meta = self._state_metadata[state] self._window.set_title(escape_markup( state_meta["title"])) return True
def _make_rename_box(self): vbox = Gtk.VBox() hbox = Gtk.HBox() repo_box = Gtk.VBox() repo_label = Gtk.Label() repo_label.set_markup( escape_markup(_("Repository name"))) repo_label.set_alignment(0.0, 0.50) repo_label.set_padding(-1, 5) repo_box.pack_start(repo_label, False, False, 0) self._repo_entry = Gtk.Entry() self._repo_entry.set_text(self._repo.repository()) repo_box.pack_start(self._repo_entry, False, False, 0) hbox.pack_start(repo_box, False, False, 0) hbox.set_property("expand", True) self._repo_message = Gtk.Label() self._repo_message.set_no_show_all(True) self._repo_message.set_alignment(0.0, 1.0) self._repo_message.set_padding(10, 5) self._repo_message.set_name("message-area-error") hbox.pack_start(self._repo_message, False, False, 0) vbox.pack_start(hbox, False, False, 0) return vbox
def _notify_vote_submit(self, app, username, vote): """ Notify User about Comment submission with current credentials. """ msg = ngettext( "Rate <b>%s</b> as <b>%s</b>, with <b>%d</b> star?", "Rate <b>%s</b> as <b>%s</b>, with <b>%d</b> stars?", vote, ) msg = msg % (app.name, escape_markup(username), vote) box = NotificationBox(msg, message_type=Gtk.MessageType.INFO, context_id=self.VOTE_NOTIFICATION_CONTEXT_ID) def _vote_submit(widget): self._vote_submit(app, username, vote) box.add_button(_("_Ok, cool!"), _vote_submit) def _send_vote(): self._on_stars_clicked(self._stars, app=app) def _logout_webservice(widget): self._logout_webservice(app, _send_vote) box.add_button(_("_No, logout!"), _logout_webservice) box.add_destroy_button(_("_Later")) self._nc.append(box)
def _change_view_state(self, state, lock=False, _ignore_lock=False, payload=None): """ Change Rigo Application UI state. You can pass a custom widget that will be shown in case of static view state. """ with self._state_mutex: if self._current_state_lock and not _ignore_lock: const_debug_write(__name__, "cannot change view state, UI locked") return False txc = self._state_transitions.get(state) if txc is None: raise AttributeError("wrong view state") enter_st, exit_st = txc current_enter_st, current_exit_st = \ self._state_transitions.get( self._current_state) # exit from current state current_exit_st() # enter the new state enter_st() self._current_state = state if lock: self._current_state_lock = True state_meta = self._state_metadata[state] self._window.set_title(escape_markup(state_meta["title"])) return True
def get_markup(self): """ Return ConfigurationUpdate markup text. """ source = escape_markup(self.root() + self.source()) dest = escape_markup(self.root() + self.destination()) apps = self.apps() msg = "<b>%s</b>\n<small><u>%s</u>: <i>%s</i></small>" % ( source, _("Destination"), dest) if apps: apps_msg = "\n<small><u>%s</u>: %s</small>" % ( _("Applications"), ", ".join(["<i>" + x.name + "</i>" for x in apps]), ) msg += apps_msg return prepare_markup(msg)
def _easter_eggs(self): """ Moo! """ msg = None if entropy.tools.is_st_valentine(): msg = escape_markup(_("Happy St. Valentine <3 <3 !")) elif entropy.tools.is_xmas(): msg = escape_markup(_("Merry Xmas \o/ !")) elif entropy.tools.is_april_first(): msg = escape_markup(_("<=|=< (this is optimistically a fish)")) if msg is not None: box = NotificationBox( msg, message_type=Gtk.MessageType.INFO, context_id="EasterEggs") box.add_destroy_button(_("Woot, thanks")) self._nc.append(box)
def _setup_application_stats(self, stats, icon): """ Setup widgets related to Application statistics (and icon). """ total_downloads = stats.downloads_total if total_downloads < 0: down_msg = escape_markup(_("Not available")) elif not total_downloads: down_msg = escape_markup(_("Never downloaded")) else: down_msg = "<small><b>%s</b> %s</small>" % (stats.downloads_total_markup, escape_markup(_("downloads"))) self._app_downloaded_lbl.set_markup(down_msg) if icon: self._image.set_from_pixbuf(icon) self._stars.set_rating(stats.ratings_average) self._stars_alignment.show_all()
def onDeleteWindow(self, window, event): # if UI is locked, do not allow to close Rigo if self._app.is_ui_locked() or \ self._service.local_activity() != LocalActivityStates.READY: rc = self._app._show_yesno_dialog( None, escape_markup(_("Hey hey hey!")), escape_markup(_("Rigo is working, are you sure?"))) if rc == Gtk.ResponseType.NO: return True while True: try: entropy.tools.kill_threads() Gtk.main_quit((window, event)) except KeyboardInterrupt: continue break
def _notify(): msg = "%s: %s" % ( _("Cannot save configuration file"), self.source(),) box = NotificationBox( escape_markup(msg), message_type=Gtk.MessageType.ERROR, context_id="ConfigUpdateErrorContextId") self._nc.append(box)
def get_markup(self): """ Return ConfigurationUpdate markup text. """ categories = self.categories() max_cat = 4 max_cat_str = "" if len(categories) > max_cat: max_cat_str = " ..." cat_str = ", ".join( ["<b>%s</b>" % x for x in categories[:max_cat]]) msg = "<b>%s</b>\n<small><i>%s</i>\n%s%s</small>" msg = msg % ( escape_markup(self.name()), escape_markup(self.description()), prepare_markup(cat_str), prepare_markup(max_cat_str)) return prepare_markup(msg)
def set_progress_text(self, text): """ Set Progress Bar text. The same will be escaped and cleaned out by the callee. """ if not self._progress_bar_shown: self._progress_bar.show() self._progress_bar_shown = True self._progress_bar.set_text(escape_markup(text))
def _notify(): msg = "%s: %s" % ( _("Cannot save configuration file"), self.source(), ) box = NotificationBox(escape_markup(msg), message_type=Gtk.MessageType.ERROR, context_id="ConfigUpdateErrorContextId") self._nc.append(box)
def _build_app_str_list(self, apps): app_lst = [] for app in apps: app_name = escape_markup(app.name) pkg_id, pkg_repo = app.get_details().pkg app_str = "<b><a href=\"%d|%s\">%s</a></b>" % ( pkg_id, pkg_repo, app_name) app_lst.append(app_str) return prepare_markup("<small>" + \ ", ".join(app_lst) + "</small>")
def _build_app_str_list(self, apps): app_lst = [] for app in apps: app_name = escape_markup(app.name) pkg_id, pkg_repo = app.get_details().pkg app_str = "<b><a href=\"%d|%s\">%s</a></b>" % (pkg_id, pkg_repo, app_name) app_lst.append(app_str) return prepare_markup("<small>" + \ ", ".join(app_lst) + "</small>")
def _easter_eggs(self): """ Moo! """ msg = None if entropy.tools.is_st_valentine(): msg = escape_markup(_("Happy St. Valentine <3 <3 !")) elif entropy.tools.is_xmas(): msg = escape_markup(_("Merry Xmas \o/ !")) elif entropy.tools.is_author_bday(): msg = escape_markup(_("Happy birthday to my authoooooor!")) elif entropy.tools.is_april_first(): msg = escape_markup(_("<=|=< (this is optimistically a fish)")) if msg is not None: box = NotificationBox(msg, message_type=Gtk.MessageType.INFO, context_id="EasterEggs") box.add_destroy_button(_("Woot, thanks")) self._nc.append(box)
def _setup_application_stats(self, stats, icon): """ Setup widgets related to Application statistics (and icon). """ total_downloads = stats.downloads_total if total_downloads < 0: down_msg = escape_markup(_("Not available")) elif not total_downloads: down_msg = escape_markup(_("Never downloaded")) else: down_msg = "<small><b>%s</b> %s</small>" % ( stats.downloads_total_markup, escape_markup(_("downloads")), ) self._app_downloaded_lbl.set_markup(down_msg) if icon: self._image.set_from_pixbuf(icon) self._stars.set_rating(stats.ratings_average) self._stars_alignment.show_all()
def _setup_terminal_menu(self): """ Setup TerminalWidget Right Click popup-menu. """ self._terminal_menu = Gtk.Menu() sall_menu_item = Gtk.ImageMenuItem.new_from_stock( "gtk-select-all", None) sall_menu_item.connect("activate", self._on_terminal_select_all) self._terminal_menu.append(sall_menu_item) copy_menu_item = Gtk.ImageMenuItem.new_from_stock("gtk-copy", None) copy_menu_item.connect("activate", self._on_terminal_copy) self._terminal_menu.append(copy_menu_item) reset_menu_item = Gtk.ImageMenuItem.new_from_stock("gtk-clear", None) reset_menu_item.connect("activate", self._on_terminal_reset) self._terminal_menu.append(reset_menu_item) black_menu_item = Gtk.ImageMenuItem.new_with_label( escape_markup(_("Black on White"))) black_menu_item.connect("activate", self._on_terminal_color, True) self._terminal_menu.append(black_menu_item) white_menu_item = Gtk.ImageMenuItem.new_with_label( escape_markup(_("White on Black"))) white_menu_item.connect("activate", self._on_terminal_color, False) self._terminal_menu.append(white_menu_item) self._autoscroll_enable_text = escape_markup( _("Enable automatic scrolling")) self._autoscroll_disable_text = escape_markup( _("Disable automatic scrolling")) self._autoscroll_menu_item = Gtk.ImageMenuItem.new_with_label( self._autoscroll_enable_text) self._autoscroll_menu_item.connect("activate", self._on_terminal_autoscroll) self._terminal_menu.append(self._autoscroll_menu_item) self._terminal_menu.show_all()
def _setup_buttons(self, app, is_installed, is_updatable): """ Setup Application View Buttons (Install/Remove/Update). """ button_area = self._app_button_area for child in button_area.get_children(): child.destroy() daemon_action = self._get_app_transaction(app) if daemon_action is not None: button = Gtk.Button() if daemon_action == DaemonAppActions.INSTALL: button.set_label(escape_markup("Installing")) elif daemon_action == DaemonAppActions.REMOVE: button.set_label(escape_markup("Removing")) button.set_sensitive(False) button_area.pack_start(button, False, False, 0) else: if is_installed: if is_updatable: update_button = Gtk.Button() update_button.set_label(escape_markup(_("Update"))) def _on_app_update(widget): return self._on_app_install(widget, app) update_button.connect("clicked", _on_app_update) button_area.pack_start(update_button, False, False, 0) else: reinstall_button = Gtk.Button() reinstall_button.set_label(escape_markup(_("Reinstall"))) def _on_app_reinstall(widget): return self._on_app_install(widget, app) reinstall_button.connect("clicked", _on_app_reinstall) button_area.pack_start(reinstall_button, False, False, 0) remove_button = Gtk.Button() remove_button.set_label(escape_markup(_("Remove"))) def _on_app_remove(widget): return self._on_app_remove(widget, app) remove_button.connect("clicked", _on_app_remove) button_area.pack_start(remove_button, False, False, 0) else: install_button = Gtk.Button() install_button.set_label(escape_markup(_("Install"))) def _on_app_install(widget): return self._on_app_install(widget, app) install_button.connect("clicked", _on_app_install) button_area.pack_start(install_button, False, False, 0) button_area.show_all()
def _make_login_box(self): vbox = Gtk.VBox() hbox = Gtk.HBox() username_box = Gtk.VBox() username_label = Gtk.Label() username_label.set_markup("<small>" + \ escape_markup(_("Username")) + "</small>") username_label.set_alignment(0.0, 0.50) username_box.pack_start(username_label, False, False, 0) self._username_entry = Gtk.Entry() username_box.pack_start(self._username_entry, False, False, 0) hbox.pack_start(username_box, False, False, 0) password_box = Gtk.VBox() password_label = Gtk.Label() password_label.set_markup("<small>" + \ escape_markup(_("Password")) + "</small>") password_label.set_alignment(0.0, 0.50) password_box.pack_start(password_label, False, False, 0) self._password_entry = Gtk.Entry() self._password_entry.set_visibility(False) password_box.pack_start(self._password_entry, False, False, 0) hbox.pack_start(password_box, True, False, 0) hbox.set_property("expand", True) vbox.pack_start(hbox, False, False, 0) self._login_message = Gtk.Label() self._login_message.set_no_show_all(True) self._login_message.set_alignment(0.0, 1.0) self._login_message.set_padding(-1, 8) self._login_message.set_name("message-area-error") vbox.pack_start(self._login_message, False, False, 0) return vbox
def _on_comment_login_success(self, widget, username, app): """ Notify user that we successfully logged in! """ box = NotificationBox( _("Logged in as <b>%s</b>! How about your <b>comment</b>?") \ % (escape_markup(username),), message_type=Gtk.MessageType.INFO, context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID) def _send_comment(widget): self._on_send_comment(widget, app=app) box.add_button(_("_Send now"), _send_comment) box.add_destroy_button(_("_Later")) self._nc.append(box)
def set_progress(self, fraction, text=None): """ Set Progress Bar progress, progress must be a value between 0.0 and 1.0. You can also provide a new text for progress at the same time, the same will be escaped and cleaned out by the callee. """ if not self._progress_bar_shown: self._progress_bar.show() self._progress_bar_shown = True self._progress_bar.set_fraction(fraction) if text is not None: self._progress_bar.set_text(escape_markup(text)) self._progress_bar.set_show_text(text is not None)
def _show_removal_error(self, err): """ During Comment removal, the WebService raised an auth error """ msg = "<b>%s</b>: %s" % ( escape_markup(_("Cannot remove comment")), err) box = NotificationBox( msg, message_type=Gtk.MessageType.ERROR, context_id=self.COMMENT_REMOVE_NOTIFICATION_CONTEXT) box.add_destroy_button(_("_Ok, thanks")) self._nc.append(box) self.show()
def _on_stars_login_success(self, widget, username, app): """ Notify user that we successfully logged in! """ box = NotificationBox( _("Logged in as <b>%s</b>! How about your <b>vote</b>?") \ % (escape_markup(username),), message_type=Gtk.MessageType.INFO, context_id=self.VOTE_NOTIFICATION_CONTEXT_ID) def _send_vote(widget): self._on_stars_clicked(self._stars, app=app) box.add_button(_("_Vote now"), _send_vote) box.add_destroy_button(_("_Later")) self._nc.append(box)
def configure_geometry(self, layout): self._layout_reset(layout) max_size = (0,0) for k, variant in self.markup_variants.items(): safe_markup = escape_markup(variant) layout.set_markup(safe_markup, -1) size = layout.get_size() max_size = max(max_size, size) w, h = max_size w /= Pango.SCALE h /= Pango.SCALE w = w+2*self.xpad h = h+2*self.ypad self.set_size(w, h)
def render(self): vbox = Gtk.VBox() hbox = Gtk.HBox() vbox.pack_start(hbox, False, False, 0) use_missing = False image_path = self._image.local_document() if not os.path.isfile(image_path): img_buf = self._missing_icon use_missing = True else: img = Gtk.Image.new_from_file(image_path) img_buf = img.get_pixbuf() if img_buf is None: use_missing = True img_buf = self._missing_icon del img w, h = img_buf.get_width(), img_buf.get_height() del img_buf if w < 1: # not legit use_missing = True img_buf = self._missing_icon width = ImageBox.IMAGE_SIZE height = width * h / w if not use_missing: try: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( image_path, width, height) except GObject.GError: try: os.remove(image_path) except OSError: pass pixbuf = self._missing_icon use_missing = True else: pixbuf = self._missing_icon event_image = Gtk.EventBox() image = Gtk.Image.new_from_pixbuf(pixbuf) event_image.add(image) event_image.connect("button-press-event", self._on_image_clicked) event_image.connect("leave-notify-event", self._on_image_leave) event_image.connect("enter-notify-event", self._on_image_enter) hbox.pack_start(event_image, False, False, 2) right_vbox = Gtk.VBox() right_align = Gtk.Alignment() right_align.set_padding(0, 0, 8, 0) right_align.add(right_vbox) ts_id = Document.DOCUMENT_TIMESTAMP_ID user_id = DocumentFactory.DOCUMENT_USERNAME_ID label = Gtk.Label() time_str = entropy.tools.convert_unix_time_to_human_time( self._image[ts_id]) time_str = escape_markup(time_str) label.set_markup( "<small><b>%s</b>" % (escape_markup(self._image[user_id]),) \ + ", <i>" + time_str + "</i>" \ + "</small>") label.set_line_wrap(True) label.set_line_wrap_mode(Pango.WrapMode.WORD) label.set_alignment(0.0, 1.0) label.set_selectable(True) label.set_name("image-box-author") right_vbox.pack_start(label, False, False, 0) # title, keywords, ddata, document_id title = self._image['title'].strip() if title: title_id = Document.DOCUMENT_TITLE_ID label = Gtk.Label() label.set_markup("<b>" + escape_markup(self._image[title_id]) + "</b>") label.set_name("image-box-title") label.set_line_wrap(True) label.set_line_wrap_mode(Pango.WrapMode.WORD) label.set_alignment(0.0, 0.0) label.set_selectable(True) right_vbox.pack_start(label, False, False, 0) desc_id = Document.DOCUMENT_DESCRIPTION_ID label = Gtk.Label() label_align = Gtk.Alignment() label_align.set_padding(0, 5, 0, 0) label_align.add(label) label.set_markup("<small>" + escape_markup(self._image[desc_id]) + "</small>") label.set_name("image-box-description") label.set_line_wrap(True) label.set_line_wrap_mode(Pango.WrapMode.WORD) label.set_alignment(0.0, 0.0) label.set_selectable(True) right_vbox.pack_start(label_align, False, False, 0) keywords_id = Document.DOCUMENT_KEYWORDS_ID label = Gtk.Label() keywords_txt = "<b>%s:</b> " % (escape_markup(_("Keywords")), ) label.set_markup( "<small>" + keywords_txt + \ escape_markup(self._image[keywords_id]) + "</small>") label.set_name("image-box-keywords") label.set_line_wrap(True) label.set_line_wrap_mode(Pango.WrapMode.WORD) label.set_alignment(0.0, 0.0) label.set_selectable(True) right_vbox.pack_start(label, False, False, 0) hbox.pack_start(right_align, True, True, 0) self.pack_start(vbox, False, False, 0) vbox.show_all()
def _permissions_setup(self): """ Check execution privileges and spawn the Rigo UI. """ if not entropy.tools.is_user_in_entropy_group(): # otherwise the lock handling would potentially # fail. self._show_ok_dialog( None, escape_markup(_("Not authorized")), escape_markup(_("You are not authorized to run Rigo"))) entropy.tools.kill_threads() Gtk.main_quit() return if not self._service.service_available(): self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup(_("RigoDaemon service is not available"))) entropy.tools.kill_threads() Gtk.main_quit() return supported_apis = self._service.supported_apis() daemon_api = self._service.api() if daemon_api not in supported_apis: self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup( _("API mismatch, please update Rigo and RigoDaemon"))) entropy.tools.kill_threads() Gtk.main_quit() return lock = EntropyResourcesLock(output=self._entropy) # always execute this from the MainThread, since the lock uses TLS acquired = lock.try_acquire_shared() is_exclusive = False if not acquired: # check whether RigoDaemon is running in excluive mode # and ignore non-atomicity here (failing with error # is acceptable) if not self._service.exclusive(): self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup(_("Another Application Manager is active"))) entropy.tools.kill_threads() Gtk.main_quit() return is_exclusive = True # otherwise we can go ahead and handle our state later # check RigoDaemon, don't worry about races between Rigo Clients # it is fine to have multiple Rigo Clients connected. Mutual # exclusion is handled via Entropy Resources Lock (which is a file # based rwsem). activity = self._service.activity() if activity != DaemonActivityStates.AVAILABLE: msg = "" show_dialog = True if activity == DaemonActivityStates.NOT_AVAILABLE: msg = _("Background Service is currently not available") elif activity == DaemonActivityStates.UPDATING_REPOSITORIES: show_dialog = False task = ParallelTask(self._service._update_repositories, [], False, master=False) task.daemon = True task.name = "UpdateRepositoriesUnlocked" task.start() elif activity == DaemonActivityStates.MANAGING_APPLICATIONS: show_dialog = False task = ParallelTask(self._service._application_request, None, None, master=False) task.daemon = True task.name = "ApplicationRequestUnlocked" task.start() elif activity == DaemonActivityStates.UPGRADING_SYSTEM: show_dialog = False task = ParallelTask(self._service._upgrade_system, False, master=False) task.daemon = True task.name = "UpgradeSystemUnlocked" task.start() elif activity == DaemonActivityStates.INTERNAL_ROUTINES: msg = _("Background Service is currently busy") else: msg = _("Background Service is incompatible with Rigo") if show_dialog: self._show_ok_dialog(None, escape_markup(_("Rigo")), escape_markup(msg)) entropy.tools.kill_threads() Gtk.main_quit() return elif is_exclusive: msg = _("Background Service is currently unavailable") # no lock acquired, cannot continue the initialization self._show_ok_dialog(None, escape_markup(_("Rigo")), escape_markup(msg)) entropy.tools.kill_threads() Gtk.main_quit() return parser = argparse.ArgumentParser( description=_("Rigo Application Browser")) parser.add_argument("package", nargs='?', type=file, metavar="<path>", help="package path") parser.add_argument("--install", metavar="<dep string>", help="install given dependency") parser.add_argument("--remove", metavar="<dep string>", help="remove given dependency") parser.add_argument("--upgrade", help="upgrade the system", action="store_true", default=False) parser.add_argument("--dumper", help="enable the main thread dumper (debug)", action="store_true", default=False) parser.add_argument("--debug", help="enable Entropy Library debug mode", action="store_true", default=False) try: self._nsargs = parser.parse_args(sys.argv[1:]) except IOError as err: self._show_ok_dialog(None, escape_markup(_("Rigo")), escape_markup("%s" % (err, ))) entropy.tools.kill_threads() Gtk.main_quit() return self._thread_dumper() self._pref_view_c.setup() self._group_view_c.setup() self._config_view_c.setup() self._repo_view_c.setup() self._notice_view_c.setup() self._app_view_c.setup() self._avc.setup() self._nc.setup() self._work_view_c.setup() self._service.setup(acquired) self._easter_eggs() self._window.show() managing = self._start_managing() if not managing: self._change_view_state(RigoViewStates.GROUPS_VIEW_STATE) self._service.hello()
def _setup_buttons(self, app, is_installed, is_updatable): """ Setup Application View Buttons (Install/Remove/Update). """ button_area = self._app_button_area for child in button_area.get_children(): child.destroy() daemon_action = self._get_app_transaction(app) daemon_activity = self._service.activity() if daemon_activity == DaemonActivityStates.UPGRADING_SYSTEM: # If we are upgrading the system, do not show any buttons const_debug_write(__name__, "system is being upgraded, hide buttons") pass elif daemon_action is not None: button = Gtk.Button() if daemon_action == DaemonAppActions.INSTALL: button.set_label(escape_markup("Installing")) elif daemon_action == DaemonAppActions.REMOVE: button.set_label(escape_markup("Removing")) button.set_sensitive(False) button_area.pack_start(button, False, False, 0) else: if is_installed: if is_updatable: update_button = Gtk.Button() update_button.set_label(escape_markup(_("Update"))) def _on_app_update(widget): return self._on_app_install(widget, app) update_button.connect("clicked", _on_app_update) button_area.pack_start(update_button, False, False, 0) else: reinstall_button = Gtk.Button() reinstall_button.set_label(escape_markup(_("Reinstall"))) def _on_app_reinstall(widget): return self._on_app_install(widget, app) reinstall_button.connect("clicked", _on_app_reinstall) button_area.pack_start(reinstall_button, False, False, 0) remove_button = Gtk.Button() remove_button.set_label(escape_markup(_("Remove"))) def _on_app_remove(widget): return self._on_app_remove(widget, app) remove_button.connect("clicked", _on_app_remove) button_area.pack_start(remove_button, False, False, 0) else: install_button = Gtk.Button() install_button.set_label(escape_markup(_("Install"))) def _on_app_install(widget): return self._on_app_install(widget, app) install_button.connect("clicked", _on_app_install) button_area.pack_start(install_button, False, False, 0) button_area.show_all()
def _permissions_setup(self): """ Check execution privileges and spawn the Rigo UI. """ if not entropy.tools.is_user_in_entropy_group(): # otherwise the lock handling would potentially # fail. self._show_ok_dialog( None, escape_markup(_("Not authorized")), escape_markup(_("You are not authorized to run Rigo"))) entropy.tools.kill_threads() Gtk.main_quit() return if not self._service.service_available(): self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup(_("RigoDaemon service is not available"))) entropy.tools.kill_threads() Gtk.main_quit() return supported_apis = self._service.supported_apis() daemon_api = self._service.api() if daemon_api not in supported_apis: self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup( _("API mismatch, please update Rigo and RigoDaemon"))) entropy.tools.kill_threads() Gtk.main_quit() return lock = EntropyResourcesLock(output=self._entropy) # always execute this from the MainThread, since the lock uses TLS acquired = lock.try_acquire_shared() is_exclusive = False if not acquired: # check whether RigoDaemon is running in excluive mode # and ignore non-atomicity here (failing with error # is acceptable) if not self._service.exclusive(): self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup(_("Another Application Manager is active"))) entropy.tools.kill_threads() Gtk.main_quit() return is_exclusive = True # otherwise we can go ahead and handle our state later # check RigoDaemon, don't worry about races between Rigo Clients # it is fine to have multiple Rigo Clients connected. Mutual # exclusion is handled via Entropy Resources Lock (which is a file # based rwsem). activity = self._service.activity() if activity != DaemonActivityStates.AVAILABLE: msg = "" show_dialog = True if activity == DaemonActivityStates.NOT_AVAILABLE: msg = _("Background Service is currently not available") elif activity == DaemonActivityStates.UPDATING_REPOSITORIES: show_dialog = False task = ParallelTask( self._service._update_repositories, [], False, master=False) task.daemon = True task.name = "UpdateRepositoriesUnlocked" task.start() elif activity == DaemonActivityStates.MANAGING_APPLICATIONS: show_dialog = False task = ParallelTask( self._service._application_request, None, None, master=False) task.daemon = True task.name = "ApplicationRequestUnlocked" task.start() elif activity == DaemonActivityStates.UPGRADING_SYSTEM: show_dialog = False task = ParallelTask( self._service._upgrade_system, False, master=False) task.daemon = True task.name = "UpgradeSystemUnlocked" task.start() elif activity == DaemonActivityStates.INTERNAL_ROUTINES: msg = _("Background Service is currently busy") else: msg = _("Background Service is incompatible with Rigo") if show_dialog: self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup(msg)) entropy.tools.kill_threads() Gtk.main_quit() return elif is_exclusive: msg = _("Background Service is currently unavailable") # no lock acquired, cannot continue the initialization self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup(msg)) entropy.tools.kill_threads() Gtk.main_quit() return parser = argparse.ArgumentParser( description=_("Rigo Application Browser")) parser.add_argument( "package", nargs='?', type=file, metavar="<path>", help="package path") parser.add_argument( "--install", metavar="<dep string>", help="install given dependency") parser.add_argument( "--remove", metavar="<dep string>", help="remove given dependency") parser.add_argument( "--upgrade", help="upgrade the system", action="store_true", default=False) parser.add_argument( "--dumper", help="enable the main thread dumper (debug)", action="store_true", default=False) parser.add_argument( "--debug", help="enable Entropy Library debug mode", action="store_true", default=False) try: self._nsargs = parser.parse_args(sys.argv[1:]) except IOError as err: self._show_ok_dialog( None, escape_markup(_("Rigo")), escape_markup("%s" % (err,))) entropy.tools.kill_threads() Gtk.main_quit() return self._thread_dumper() self._pref_view_c.setup() self._group_view_c.setup() self._config_view_c.setup() self._repo_view_c.setup() self._notice_view_c.setup() self._app_view_c.setup() self._avc.setup() self._nc.setup() self._work_view_c.setup() self._service.setup(acquired) self._easter_eggs() self._window.show() managing = self._start_managing() if not managing: self._change_view_state(RigoViewStates.GROUPS_VIEW_STATE) self._service.hello()
def _setup_buttons(self, app, is_installed, is_updatable): """ Setup Application View Buttons (Install/Remove/Update). """ button_area = self._app_button_area for child in button_area.get_children(): child.destroy() daemon_action = self._get_app_transaction(app) daemon_activity = self._service.activity() if daemon_activity == DaemonActivityStates.UPGRADING_SYSTEM: # If we are upgrading the system, do not show any buttons const_debug_write( __name__, "system is being upgraded, hide buttons") pass elif daemon_action is not None: button = Gtk.Button() if daemon_action == DaemonAppActions.INSTALL: button.set_label(escape_markup("Installing")) elif daemon_action == DaemonAppActions.REMOVE: button.set_label(escape_markup("Removing")) button.set_sensitive(False) button_area.pack_start( button, False, False, 0) else: if is_installed: if is_updatable: update_button = Gtk.Button() update_button.set_label( escape_markup(_("Update"))) def _on_app_update(widget): return self._on_app_install(widget, app) update_button.connect("clicked", _on_app_update) button_area.pack_start(update_button, False, False, 0) else: reinstall_button = Gtk.Button() reinstall_button.set_label( escape_markup(_("Reinstall"))) def _on_app_reinstall(widget): return self._on_app_install(widget, app) reinstall_button.connect("clicked", _on_app_reinstall) button_area.pack_start(reinstall_button, False, False, 0) remove_button = Gtk.Button() remove_button.set_label( escape_markup(_("Remove"))) def _on_app_remove(widget): return self._on_app_remove(widget, app) remove_button.connect("clicked", _on_app_remove) button_area.pack_start(remove_button, False, False, 0) else: install_button = Gtk.Button() install_button.set_label( escape_markup(_("Install"))) def _on_app_install(widget): return self._on_app_install(widget, app) install_button.connect("clicked", _on_app_install) button_area.pack_start(install_button, False, False, 0) button_area.show_all()