[Rigo] implement a Bottom NotificationBox "Activity" button
This Button allows users to see the current Application management queue by leveraging the new RigoDaemon API.
This commit is contained in:
@@ -856,7 +856,8 @@ class Application(object):
|
||||
return self._licenses
|
||||
|
||||
def __init__(self, entropy_client, entropy_ws, rigo_service,
|
||||
package_match, redraw_callback=None, package_path=None):
|
||||
package_match, redraw_callback=None, package_path=None,
|
||||
children=None, vanished_callback=None):
|
||||
self._entropy = entropy_client
|
||||
self._entropy_ws = entropy_ws
|
||||
self._service = rigo_service
|
||||
@@ -864,6 +865,8 @@ class Application(object):
|
||||
self._pkg_id, self._repo_id = package_match
|
||||
self._path = package_path
|
||||
self._redraw_callback = redraw_callback
|
||||
self._children = children
|
||||
self._vanished_callback = vanished_callback
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -873,6 +876,8 @@ class Application(object):
|
||||
repo = self._entropy.open_repository(self._repo_id)
|
||||
name = repo.retrieveName(self._pkg_id)
|
||||
if name is None:
|
||||
if self._vanished_callback is not None:
|
||||
self._vanished_callback(self)
|
||||
return _("N/A")
|
||||
name = " ".join([x.capitalize() for x in \
|
||||
name.replace("-"," ").split()])
|
||||
@@ -888,6 +893,15 @@ class Application(object):
|
||||
"""
|
||||
return self._path
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
"""
|
||||
If the Application is the parent of other Applications,
|
||||
this object shall contain a list of children Application
|
||||
objects. Otherwise, it returns None.
|
||||
"""
|
||||
return self._children
|
||||
|
||||
def is_installed(self):
|
||||
"""
|
||||
Return if Application is currently installed.
|
||||
@@ -931,9 +945,7 @@ class Application(object):
|
||||
# in the installed packages repository, matches
|
||||
# must be of length < 2.
|
||||
if len(matches) > 1:
|
||||
raise AttributeError(
|
||||
"searchKeySlot for %s returned: %s" % (
|
||||
(key, slot), matches,))
|
||||
return None
|
||||
if not matches:
|
||||
# not installed
|
||||
return None
|
||||
@@ -1232,6 +1244,10 @@ class Application(object):
|
||||
self._entropy.rwsem().reader_acquire()
|
||||
try:
|
||||
repo = self._entropy.open_repository(self._repo_id)
|
||||
if self._vanished_callback is not None:
|
||||
if not repo.isPackageIdAvailable(self._pkg_id):
|
||||
self._vanished_callback(self)
|
||||
|
||||
version = repo.retrieveVersion(self._pkg_id)
|
||||
if version is None:
|
||||
version = _("N/A")
|
||||
@@ -1271,6 +1287,10 @@ class Application(object):
|
||||
self._entropy.rwsem().reader_acquire()
|
||||
try:
|
||||
repo = self._entropy.open_repository(self._repo_id)
|
||||
if self._vanished_callback is not None:
|
||||
if not repo.isPackageIdAvailable(self._pkg_id):
|
||||
self._vanished_callback(self)
|
||||
|
||||
inst_repo = self._entropy.installed_repository()
|
||||
strict = repo.getStrictData(self._pkg_id)
|
||||
if strict is None:
|
||||
@@ -1347,6 +1367,10 @@ class Application(object):
|
||||
lic_url = "%s/license/" % (etpConst['packages_website_url'],)
|
||||
repo = self._entropy.open_repository(self._repo_id)
|
||||
|
||||
if self._vanished_callback is not None:
|
||||
if not repo.isPackageIdAvailable(self._pkg_id):
|
||||
self._vanished_callback(self)
|
||||
|
||||
licenses = repo.retrieveLicense(self._pkg_id)
|
||||
if licenses:
|
||||
licenses_txt = "<b>%s</b>: " % (escape_markup(_("License")),)
|
||||
|
||||
@@ -78,9 +78,10 @@ class ApplicationsViewController(GObject.Object):
|
||||
MIN_RECENT_SEARCH_KEY_LEN = 2
|
||||
|
||||
SHOW_INSTALLED_KEY = "in:installed"
|
||||
SHOW_QUEUE_KEY = "in:queue"
|
||||
|
||||
def __init__(self, activity_rwsem, entropy_client, entropy_ws,
|
||||
nc, rigo_service, prefc, icons, nf_box,
|
||||
nc, bottom_nc, rigo_service, prefc, icons, nf_box,
|
||||
search_entry, search_entry_completion,
|
||||
search_entry_store, store, view):
|
||||
GObject.Object.__init__(self)
|
||||
@@ -97,6 +98,7 @@ class ApplicationsViewController(GObject.Object):
|
||||
self._not_found_search_box = None
|
||||
self._not_found_label = None
|
||||
self._nc = nc
|
||||
self._bottom_nc = bottom_nc
|
||||
self._prefc = prefc
|
||||
|
||||
self._cacher = EntropyCacher()
|
||||
@@ -333,6 +335,39 @@ class ApplicationsViewController(GObject.Object):
|
||||
__name__, "upgrade:"
|
||||
" upgrade_system() sent")
|
||||
|
||||
def _show_action_queue_items(self, _invalid_matches=False):
|
||||
"""
|
||||
Request the UI to show the current Action Queue, if any.
|
||||
"""
|
||||
const_debug_write(
|
||||
__name__, "_show_action_queue_items called")
|
||||
apps = self._service.action_queue_items()
|
||||
const_debug_write(
|
||||
__name__, "_show_action_queue_items, items: %d" % (len(apps),))
|
||||
|
||||
matches = []
|
||||
if not _invalid_matches:
|
||||
for app in apps:
|
||||
const_debug_write(
|
||||
__name__, "_show_action_queue_items:"
|
||||
" %s" % (app,))
|
||||
matches.append(app.get_details().pkg)
|
||||
else:
|
||||
self._entropy.rwsem().reader_acquire()
|
||||
try:
|
||||
inst_repo = self._entropy.installed_repository()
|
||||
repo_name = inst_repo.repository_id()
|
||||
matches.extend(
|
||||
[(-2, repo_name),
|
||||
(-5, repo_name),
|
||||
(-10, repo_name)])
|
||||
finally:
|
||||
self._entropy.rwsem().reader_release()
|
||||
|
||||
if matches:
|
||||
self.set_many_safe(matches,
|
||||
_from_search=ApplicationsViewController.SHOW_QUEUE_KEY)
|
||||
|
||||
def __simulate_orphaned_apps(self, text):
|
||||
|
||||
const_debug_write(
|
||||
@@ -368,6 +403,9 @@ class ApplicationsViewController(GObject.Object):
|
||||
elif text == "in:confupdate":
|
||||
self._service.configuration_updates()
|
||||
return
|
||||
elif text == ApplicationsViewController.SHOW_QUEUE_KEY:
|
||||
self._show_action_queue_items()
|
||||
return
|
||||
elif text == "in:config":
|
||||
GLib.idle_add(self.emit, "view-want-change",
|
||||
RigoViewStates.PREFERENCES_VIEW_STATE,
|
||||
@@ -403,9 +441,12 @@ class ApplicationsViewController(GObject.Object):
|
||||
if sim_str:
|
||||
self.__simulate_orphaned_apps(sim_str)
|
||||
return
|
||||
if text == "in:simulate:u":
|
||||
elif text == "in:simulate:u":
|
||||
self.upgrade(simulate=True)
|
||||
return
|
||||
elif text == "in:simulate:v":
|
||||
self._show_action_queue_items(_invalid_matches=True)
|
||||
return
|
||||
|
||||
return self.__search_thread_body(text)
|
||||
|
||||
@@ -655,6 +696,14 @@ class ApplicationsViewController(GObject.Object):
|
||||
"drive-harddisk", _show_installed)
|
||||
self._prefc.append(pref)
|
||||
|
||||
def _show_queue_view(widget):
|
||||
self._search(ApplicationsViewController.SHOW_QUEUE_KEY,
|
||||
_force=True)
|
||||
self._bottom_nc.connect("show-queue-view", _show_queue_view)
|
||||
def _clear(widget):
|
||||
self.clear()
|
||||
self._store.connect("all-vanished", _clear)
|
||||
|
||||
self._view.set_model(self._store)
|
||||
self._search_entry.connect(
|
||||
"changed", self._search_changed)
|
||||
|
||||
@@ -181,6 +181,10 @@ class BottomNotificationViewController(NotificationViewController):
|
||||
None,
|
||||
tuple(),
|
||||
),
|
||||
"show-queue-view" : (GObject.SignalFlags.RUN_LAST,
|
||||
None,
|
||||
tuple(),
|
||||
),
|
||||
"work-interrupt" : (GObject.SignalFlags.RUN_LAST,
|
||||
None,
|
||||
tuple(),
|
||||
@@ -206,6 +210,12 @@ class BottomNotificationViewController(NotificationViewController):
|
||||
"""
|
||||
self.emit("work-interrupt")
|
||||
|
||||
def _on_show_activity(self, widget):
|
||||
"""
|
||||
User is asking to show the Application Queue.
|
||||
"""
|
||||
self.emit("show-queue-view")
|
||||
|
||||
def _append_repositories_update(self):
|
||||
"""
|
||||
Add a NotificationBox related to Repositories Update
|
||||
@@ -232,6 +242,7 @@ class BottomNotificationViewController(NotificationViewController):
|
||||
w, h = self._window.get_size()
|
||||
self._window.resize(w, 1)
|
||||
box.add_button(_("Show me"), _show_me)
|
||||
box.add_button(_("Activity"), self._on_show_activity)
|
||||
box.add_button(_("Interrupt"), self._on_work_interrupt)
|
||||
self.append(box)
|
||||
|
||||
@@ -249,6 +260,7 @@ class BottomNotificationViewController(NotificationViewController):
|
||||
w, h = self._window.get_size()
|
||||
self._window.resize(w, 1)
|
||||
box.add_button(_("Show me"), _show_me)
|
||||
box.add_button(_("Activity"), self._on_show_activity)
|
||||
box.add_button(_("Interrupt"), self._on_work_interrupt)
|
||||
self.append(box)
|
||||
|
||||
|
||||
@@ -50,6 +50,12 @@ class AppListStore(Gtk.ListStore):
|
||||
None,
|
||||
(GObject.TYPE_PYOBJECT,),
|
||||
),
|
||||
# signal that all the elements in the List
|
||||
# have vanished.
|
||||
"all-vanished" : (GObject.SignalFlags.RUN_LAST,
|
||||
None,
|
||||
tuple(),
|
||||
),
|
||||
}
|
||||
|
||||
def __init__(self, entropy_client, entropy_ws, rigo_service,
|
||||
@@ -194,6 +200,41 @@ class AppListStore(Gtk.ListStore):
|
||||
AppListStore._ICON_CACHE[pkg_match] = pixbuf
|
||||
return pixbuf
|
||||
|
||||
def _vanished_callback(self, app):
|
||||
"""
|
||||
Remove elements that are marked as "vanished" due
|
||||
to unavailable metadata.
|
||||
"""
|
||||
def _remove(_app):
|
||||
pkg_match = _app.get_details().pkg
|
||||
|
||||
vis_data = self._view.get_visible_range()
|
||||
if vis_data is None:
|
||||
return
|
||||
if len(vis_data) == 2:
|
||||
# Gtk 3.4
|
||||
valid_paths = True
|
||||
start_path, end_path = vis_data
|
||||
else:
|
||||
# Gtk <3.2
|
||||
valid_paths, start_path, end_path = vis_data
|
||||
|
||||
if not valid_paths:
|
||||
return
|
||||
|
||||
path = start_path
|
||||
while path <= end_path:
|
||||
path_iter = self.get_iter(path)
|
||||
if self.iter_is_valid(path_iter):
|
||||
visible_pkg_match = self.get_value(path_iter, 0)
|
||||
if visible_pkg_match == pkg_match:
|
||||
self.remove(path_iter)
|
||||
if len(self) == 0:
|
||||
self.emit("all-vanished")
|
||||
return
|
||||
|
||||
GLib.idle_add(_remove, app)
|
||||
|
||||
def get_application(self, pkg_match):
|
||||
def _ui_redraw_callback(*args):
|
||||
if const_debug_enabled():
|
||||
@@ -203,5 +244,6 @@ class AppListStore(Gtk.ListStore):
|
||||
|
||||
app = Application(self._entropy, self._entropy_ws,
|
||||
self._service, pkg_match,
|
||||
redraw_callback=_ui_redraw_callback)
|
||||
redraw_callback=_ui_redraw_callback,
|
||||
vanished_callback=self._vanished_callback)
|
||||
return app
|
||||
|
||||
+9
-8
@@ -291,10 +291,18 @@ class Rigo(Gtk.Application):
|
||||
|
||||
self._nc = UpperNotificationViewController(
|
||||
self._entropy, self._entropy_ws, self._notification)
|
||||
# Bottom NotificationBox controller.
|
||||
# Bottom notifications are only used for
|
||||
# providing Activity control to User during
|
||||
# the Activity itself.
|
||||
self._bottom_nc = BottomNotificationViewController(
|
||||
self._window, self._bottom_notification,
|
||||
self._pref_button)
|
||||
|
||||
self._avc = ApplicationsViewController(
|
||||
self._activity_rwsem,
|
||||
self._entropy, self._entropy_ws, self._nc, self._service,
|
||||
self._entropy, self._entropy_ws,
|
||||
self._nc, self._bottom_nc, self._service,
|
||||
self._pref_view_c, icons, self._not_found_box,
|
||||
self._search_entry, self._search_entry_completion,
|
||||
self._search_entry_store, self._app_store, self._view)
|
||||
@@ -303,13 +311,6 @@ class Rigo(Gtk.Application):
|
||||
self._avc.connect("view-filled", self._on_view_filled)
|
||||
self._avc.connect("view-want-change", self._on_view_change)
|
||||
|
||||
# Bottom NotificationBox controller.
|
||||
# Bottom notifications are only used for
|
||||
# providing Activity control to User during
|
||||
# the Activity itself.
|
||||
self._bottom_nc = BottomNotificationViewController(
|
||||
self._window, self._bottom_notification,
|
||||
self._pref_button)
|
||||
self._service.set_bottom_notification_controller(
|
||||
self._bottom_nc)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user