[Rigo] implement centralized Application transaction state
This commit is contained in:
+82
-10
@@ -59,7 +59,7 @@ from entropy.core.settings.base import SystemSettings
|
||||
|
||||
import entropy.tools
|
||||
|
||||
from RigoDaemon.enums import ActivityStates
|
||||
from RigoDaemon.enums import ActivityStates, AppActions
|
||||
from RigoDaemon.config import DbusConfig
|
||||
|
||||
TEXT = TextInterface()
|
||||
@@ -168,6 +168,51 @@ class DaemonUrlFetcher(UrlFetcher):
|
||||
int(self.__remotesize), int(self.__datatransfer),
|
||||
self.__time_remaining)
|
||||
|
||||
class ApplicationsTransaction(object):
|
||||
|
||||
"""
|
||||
RigoDaemon Application Transaction Controller.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._transactions = {}
|
||||
self._transactions_mutex = Lock()
|
||||
|
||||
def set(self, package_id, repository_id, app_action):
|
||||
"""
|
||||
Set transaction state for Application.
|
||||
"""
|
||||
with self._transactions_mutex:
|
||||
match = (package_id, repository_id)
|
||||
self._transactions[match] = app_action
|
||||
|
||||
def unset(self, package_id, repository_id):
|
||||
"""
|
||||
Unset transaction state for Application.
|
||||
"""
|
||||
with self._transactions_mutex:
|
||||
match = (package_id, repository_id)
|
||||
self._transactions.pop(match, None)
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Reset all the transaction states.
|
||||
"""
|
||||
with self._transactions_mutex:
|
||||
self._transactions.clear()
|
||||
|
||||
def get(self, package_id, repository_id):
|
||||
"""
|
||||
Get transaction state (in for of AppActions enum)
|
||||
for given Application.
|
||||
"""
|
||||
with self._transactions_mutex:
|
||||
match = (package_id, repository_id)
|
||||
tx = self._transactions.get(match)
|
||||
if tx is None:
|
||||
return AppActions.IDLE
|
||||
return tx
|
||||
|
||||
|
||||
class RigoDaemonService(dbus.service.Object):
|
||||
|
||||
@@ -231,6 +276,7 @@ class RigoDaemonService(dbus.service.Object):
|
||||
bus = system_bus)
|
||||
dbus.service.Object.__init__(self, name, object_path)
|
||||
|
||||
self._txs = ApplicationsTransaction()
|
||||
# used by non-daemon thread to exit
|
||||
self._stop_signal = False
|
||||
|
||||
@@ -331,6 +377,7 @@ class RigoDaemonService(dbus.service.Object):
|
||||
self._close_local_resources()
|
||||
self._entropy_setup()
|
||||
self.activity_started(activity)
|
||||
self.activity_progress(activity, 0)
|
||||
|
||||
if not repositories:
|
||||
repositories = list(
|
||||
@@ -361,6 +408,7 @@ class RigoDaemonService(dbus.service.Object):
|
||||
"available, wtf !?!?")
|
||||
# wtf??
|
||||
self._release_exclusive(activity)
|
||||
self.activity_progress(activity, 100)
|
||||
self.activity_completed(activity, result == 0)
|
||||
self.repositories_updated(result, msg)
|
||||
|
||||
@@ -422,33 +470,36 @@ class RigoDaemonService(dbus.service.Object):
|
||||
write_output("_action_queue_worker_thread: "
|
||||
"doing %s" % (
|
||||
item,), debug=True)
|
||||
self._process_action(item)
|
||||
self._process_action(item, activity)
|
||||
|
||||
finally:
|
||||
_action_queue_finally()
|
||||
|
||||
def _process_action(self, item):
|
||||
def _process_action(self, item, activity):
|
||||
"""
|
||||
This is the real Application Action processing function.
|
||||
"""
|
||||
package_id, repository_id = item.pkg
|
||||
action = item.action()
|
||||
|
||||
self._txs.reset()
|
||||
self._txs.set(package_id, repository_id, action)
|
||||
|
||||
self.processing_application(package_id, repository_id, action)
|
||||
success = False
|
||||
try:
|
||||
self.activity_progress(activity, 0)
|
||||
# FIXME, complete
|
||||
# 1. calculate dependencies
|
||||
# 2. notify (and block) if conflicts arise
|
||||
# 3. ?? TBD show install/removal queue?
|
||||
# 4. [GUI?] if removal, ask if action is really wanted?
|
||||
# 5. [GUI?] if system package, avoid removal?
|
||||
# simulate
|
||||
self._entropy.output("Application Management Message")
|
||||
time.sleep(5)
|
||||
time.sleep(2.5)
|
||||
self.activity_progress(activity, 50)
|
||||
time.sleep(2.5)
|
||||
self._entropy.output("Application Management Complete")
|
||||
success = True
|
||||
finally:
|
||||
self.activity_progress(activity, 100)
|
||||
self._txs.reset()
|
||||
self.application_processed(
|
||||
package_id, repository_id, action, success)
|
||||
|
||||
@@ -603,6 +654,17 @@ class RigoDaemonService(dbus.service.Object):
|
||||
write_output("action_queue_length called", debug=True)
|
||||
return len(self._action_queue)
|
||||
|
||||
@dbus.service.method(BUS_NAME, in_signature='is',
|
||||
out_signature='s')
|
||||
def action(self, package_id, repository_id):
|
||||
"""
|
||||
Return Application transaction state (AppAction enum
|
||||
value)
|
||||
"""
|
||||
write_output("action called: %s, %s" % (
|
||||
package_id, repository_id,), debug=True)
|
||||
return self._txs.get(package_id, repository_id)
|
||||
|
||||
@dbus.service.method(BUS_NAME, in_signature='',
|
||||
out_signature='b')
|
||||
def exclusive(self):
|
||||
@@ -610,7 +672,7 @@ class RigoDaemonService(dbus.service.Object):
|
||||
Return whether RigoDaemon is running in with
|
||||
Entropy Resources acquired in exclusive mode.
|
||||
"""
|
||||
write_output("is_exclusive called: %s, %s", debug=True)
|
||||
write_output("exclusive called", debug=True)
|
||||
|
||||
return self._acquired_exclusive
|
||||
|
||||
@@ -705,6 +767,16 @@ class RigoDaemonService(dbus.service.Object):
|
||||
write_output("activity_started() issued for %d" % (
|
||||
activity,), debug=True)
|
||||
|
||||
@dbus.service.signal(dbus_interface=BUS_NAME,
|
||||
signature='ii')
|
||||
def activity_progress(self, activity, progress):
|
||||
"""
|
||||
Signal all the connected Clients the ongoing activity
|
||||
progress state (from 0 to 100).
|
||||
"""
|
||||
write_output("activity_progress() issued for %d, state: %i" % (
|
||||
activity, progress,), debug=True)
|
||||
|
||||
@dbus.service.signal(dbus_interface=BUS_NAME,
|
||||
signature='ib')
|
||||
def activity_completed(self, activity, success):
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
<arg name="length" type="i" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="action">
|
||||
<arg name="package_id" type="i" direction="in"/>
|
||||
<arg name="repository_id" type="s" direction="in"/>
|
||||
<arg name="action" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="exclusive">
|
||||
<arg name="status" type="b" direction="out"/>
|
||||
</method>
|
||||
|
||||
@@ -45,3 +45,4 @@ class ActivityStates:
|
||||
class AppActions:
|
||||
INSTALL = "install"
|
||||
REMOVE = "remove"
|
||||
IDLE = "idle"
|
||||
|
||||
@@ -31,6 +31,8 @@ from rigo.ui.gtk3.widgets.images import ImageBox
|
||||
from rigo.utils import build_application_store_url, \
|
||||
escape_markup, prepare_markup
|
||||
|
||||
from RigoDaemon.enums import AppActions as DaemonAppActions
|
||||
|
||||
from entropy.const import etpConst, const_debug_write, \
|
||||
const_debug_enabled, const_convert_to_unicode, const_isunicode
|
||||
from entropy.misc import ParallelTask
|
||||
@@ -90,15 +92,17 @@ class ApplicationViewController(GObject.Object):
|
||||
VOTE_NOTIFICATION_CONTEXT_ID = "VoteNotificationContext"
|
||||
COMMENT_NOTIFICATION_CONTEXT_ID = "CommentNotificationContext"
|
||||
|
||||
def __init__(self, entropy_client, entropy_ws, builder):
|
||||
def __init__(self, entropy_client, entropy_ws, rigo_service, builder):
|
||||
GObject.Object.__init__(self)
|
||||
self._builder = builder
|
||||
self._entropy = entropy_client
|
||||
self._entropy_ws = entropy_ws
|
||||
self._service = rigo_service
|
||||
self._app_store = None
|
||||
self._last_app = None
|
||||
self._nc = None
|
||||
self._avc = None
|
||||
self._visible = False
|
||||
|
||||
self._window = self._builder.get_object("rigoWindow")
|
||||
self._image = self._builder.get_object("appViewImage")
|
||||
@@ -166,6 +170,40 @@ class ApplicationViewController(GObject.Object):
|
||||
"changed", self._on_comment_buffer_changed)
|
||||
self._stars.connect("changed", self._on_stars_clicked)
|
||||
|
||||
self._service.connect(
|
||||
"application-processed", self._on_reload_state)
|
||||
self._service.connect(
|
||||
"application-processing", self._on_reload_state)
|
||||
self._service.connect(
|
||||
"application-abort", self._on_reload_state)
|
||||
|
||||
def _get_app_transaction(self, app):
|
||||
"""
|
||||
Get Application transaction state (AppAction enum).
|
||||
"""
|
||||
pkg_match = app.get_details().pkg
|
||||
local_txs = self._service.local_transactions()
|
||||
tx = local_txs.get(pkg_match)
|
||||
if tx is None:
|
||||
tx = self._service.action(app)
|
||||
if tx == DaemonAppActions.IDLE:
|
||||
tx = None
|
||||
return tx
|
||||
|
||||
def _on_reload_state(self, srv, app, daemon_action):
|
||||
"""
|
||||
Reload Application state due to a transaction event.
|
||||
"""
|
||||
if not self._visible:
|
||||
return
|
||||
last_app = self._last_app
|
||||
if last_app is not None:
|
||||
app = last_app
|
||||
task = ParallelTask(self._reload_application_state, app)
|
||||
task.daemon = True
|
||||
task.name = "OnReloadAppState"
|
||||
task.start()
|
||||
|
||||
def _on_comment_buffer_changed(self, widget):
|
||||
"""
|
||||
Our comment text is changed, decide if to activate the Send button.
|
||||
@@ -180,6 +218,7 @@ class ApplicationViewController(GObject.Object):
|
||||
information. Once we're done loading the shit, we just emit
|
||||
'application-show' and let others do the UI switch.
|
||||
"""
|
||||
self._visible = True
|
||||
self._last_app = app
|
||||
task = ParallelTask(self.__application_activate, app)
|
||||
task.name = "ApplicationActivate"
|
||||
@@ -363,6 +402,7 @@ class ApplicationViewController(GObject.Object):
|
||||
This method shall be called when the Controller widgets are
|
||||
going to hide.
|
||||
"""
|
||||
self._visible = False
|
||||
self._last_app = None
|
||||
for child in self._app_my_comments_box.get_children():
|
||||
child.destroy()
|
||||
@@ -741,40 +781,57 @@ class ApplicationViewController(GObject.Object):
|
||||
for child in button_area.get_children():
|
||||
child.destroy()
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
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)
|
||||
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()
|
||||
|
||||
@@ -798,6 +855,18 @@ class ApplicationViewController(GObject.Object):
|
||||
self._stars.set_rating(stats.ratings_average)
|
||||
self._stars_alignment.show_all()
|
||||
|
||||
def _reload_application_state(self, app):
|
||||
"""
|
||||
Reload Application state after transaction.
|
||||
"""
|
||||
is_installed = app.is_installed()
|
||||
is_updatable = app.is_updatable()
|
||||
|
||||
def _setup():
|
||||
self._setup_buttons(
|
||||
app, is_installed, is_updatable)
|
||||
GLib.idle_add(_setup)
|
||||
|
||||
def _setup_application_info(self, app, metadata):
|
||||
"""
|
||||
Setup the actual UI widgets content and emit 'application-show'
|
||||
|
||||
@@ -58,8 +58,6 @@ class AppTreeView(Gtk.TreeView):
|
||||
|
||||
self.pressed = False
|
||||
self.focal_btn = None
|
||||
# pkg match is key, AppAction is val
|
||||
self._action_block_list = {}
|
||||
self.expanded_path = None
|
||||
|
||||
#~ # if this hacked mode is available everything will be fast
|
||||
@@ -286,23 +284,24 @@ class AppTreeView(Gtk.TreeView):
|
||||
# update active app, use row-ref as argument
|
||||
self.expand_path(row)
|
||||
|
||||
app = model[row][COL_ROW_DATA]
|
||||
pkg_match = model[row][COL_ROW_DATA]
|
||||
|
||||
# make sure this is not a category (LP: #848085)
|
||||
if self.rowref_is_category(app):
|
||||
if self.rowref_is_category(pkg_match):
|
||||
return False
|
||||
|
||||
action_btn = tr.get_button_by_name(
|
||||
CellButtonIDs.ACTION)
|
||||
#if not action_btn: return False
|
||||
|
||||
app_action = self._action_block_list.get(app)
|
||||
app = self.appmodel.get_application(pkg_match)
|
||||
app_action = self._get_app_transaction(app)
|
||||
if app_action is None:
|
||||
if self.appmodel.is_installed(app):
|
||||
if self.appmodel.is_installed(pkg_match):
|
||||
action_btn.set_variant(self.VARIANT_REMOVE)
|
||||
action_btn.set_sensitive(True)
|
||||
action_btn.show()
|
||||
elif self.appmodel.is_available(app):
|
||||
elif self.appmodel.is_available(pkg_match):
|
||||
action_btn.set_variant(self.VARIANT_INSTALL)
|
||||
action_btn.set_sensitive(True)
|
||||
action_btn.show()
|
||||
@@ -310,7 +309,7 @@ class AppTreeView(Gtk.TreeView):
|
||||
action_btn.set_sensitive(False)
|
||||
action_btn.hide()
|
||||
self._apc.emit("application-selected",
|
||||
self.appmodel.get_application(app))
|
||||
app)
|
||||
return
|
||||
|
||||
if self.pressed and self.focal_btn == action_btn:
|
||||
@@ -329,15 +328,14 @@ class AppTreeView(Gtk.TreeView):
|
||||
action_btn.show()
|
||||
action_btn.set_state(Gtk.StateFlags.INSENSITIVE)
|
||||
|
||||
#~ self.emit("application-selected", self.appmodel.get_application(app))
|
||||
self._apc.emit("application-selected",
|
||||
self.appmodel.get_application(app))
|
||||
self._apc.emit("application-selected", app)
|
||||
return False
|
||||
|
||||
def _on_row_activated(self, view, path, column, tr):
|
||||
rowref = self.get_rowref(view.get_model(), path)
|
||||
|
||||
if not rowref: return
|
||||
if not rowref:
|
||||
return
|
||||
|
||||
if self.rowref_is_category(rowref): return
|
||||
|
||||
@@ -483,8 +481,8 @@ class AppTreeView(Gtk.TreeView):
|
||||
cell.set_property('isactive', is_active)
|
||||
return
|
||||
|
||||
def _app_activated_cb(self, btn, btn_id, app, store, path):
|
||||
if self.rowref_is_category(app):
|
||||
def _app_activated_cb(self, btn, btn_id, pkg_match, store, path):
|
||||
if self.rowref_is_category(pkg_match):
|
||||
return
|
||||
|
||||
# FIXME: would be nice if that would be more elegant
|
||||
@@ -493,28 +491,28 @@ class AppTreeView(Gtk.TreeView):
|
||||
if type(store) is Gtk.TreeModelFilter:
|
||||
store = store.get_model()
|
||||
|
||||
app = self.appmodel.get_application(pkg_match)
|
||||
if btn_id == CellButtonIDs.INFO:
|
||||
self._apc.emit("application-activated",
|
||||
self.appmodel.get_application(app))
|
||||
self._apc.emit("application-activated", app)
|
||||
elif btn_id == CellButtonIDs.ACTION:
|
||||
btn.set_sensitive(False)
|
||||
store.row_changed(path, store.get_iter(path))
|
||||
# be sure we dont request an action for a
|
||||
# pkg with pre-existing actions
|
||||
if app in self._action_block_list:
|
||||
daemon_action = self._get_app_transaction(app)
|
||||
if daemon_action is not None:
|
||||
logging.debug(
|
||||
"Action already in progress for match: %s" % (
|
||||
(app,)))
|
||||
(pkg_match,)))
|
||||
return False
|
||||
if self.appmodel.is_installed(app):
|
||||
if self.appmodel.is_installed(pkg_match):
|
||||
perform_action = AppActions.REMOVE
|
||||
else:
|
||||
perform_action = AppActions.INSTALL
|
||||
self._action_block_list[app] = perform_action
|
||||
self._set_app_transaction(app, perform_action)
|
||||
|
||||
self._apc.emit("application-request-action",
|
||||
self.appmodel.get_application(app),
|
||||
perform_action)
|
||||
app, perform_action)
|
||||
self.queue_draw()
|
||||
return False
|
||||
|
||||
@@ -548,8 +546,7 @@ class AppTreeView(Gtk.TreeView):
|
||||
"""
|
||||
self.emit("cursor-changed")
|
||||
# remove pkg from the block list
|
||||
pkg = app.get_details().pkg
|
||||
self._check_remove_pkg_from_blocklist(pkg)
|
||||
self._pop_app_transaction(app)
|
||||
|
||||
action_btn = tr.get_button_by_name(CellButtonIDs.ACTION)
|
||||
if action_btn:
|
||||
@@ -588,8 +585,7 @@ class AppTreeView(Gtk.TreeView):
|
||||
callback when an application install/remove
|
||||
transaction has stopped
|
||||
"""
|
||||
pkg = app.get_details().pkg
|
||||
self._check_remove_pkg_from_blocklist(pkg)
|
||||
self._pop_app_transaction(app)
|
||||
|
||||
action_btn = tr.get_button_by_name(CellButtonIDs.ACTION)
|
||||
if action_btn:
|
||||
@@ -601,8 +597,34 @@ class AppTreeView(Gtk.TreeView):
|
||||
self._set_cursor(action_btn, self._cursor_hand)
|
||||
self.queue_draw()
|
||||
|
||||
def _check_remove_pkg_from_blocklist(self, app):
|
||||
action = self._action_block_list.pop(app, None)
|
||||
def _get_app_transaction(self, app):
|
||||
"""
|
||||
Get Application transaction state (AppAction enum).
|
||||
"""
|
||||
pkg_match = app.get_details().pkg
|
||||
local_txs = self._backend.local_transactions()
|
||||
tx = local_txs.get(pkg_match)
|
||||
if tx is None:
|
||||
tx = self._backend.action(app)
|
||||
if tx == DaemonAppActions.IDLE:
|
||||
tx = None
|
||||
return tx
|
||||
|
||||
def _set_app_transaction(self, app, daemon_action):
|
||||
"""
|
||||
Set Application local transaction state (AppAction enum).
|
||||
"""
|
||||
pkg_match = app.get_details().pkg
|
||||
local_txs = self._backend.local_transactions()
|
||||
local_txs[pkg_match] = daemon_action
|
||||
|
||||
def _pop_app_transaction(self, app):
|
||||
"""
|
||||
Drop Application local transaction state.
|
||||
"""
|
||||
pkg_match = app.get_details().pkg
|
||||
local_txs = self._backend.local_transactions()
|
||||
action = local_txs.pop(pkg_match, None)
|
||||
return action
|
||||
|
||||
def _xy_is_over_focal_row(self, x, y):
|
||||
@@ -635,4 +657,3 @@ def on_entry_changed(widget, data):
|
||||
if widget.stamp:
|
||||
GObject.source_remove(widget.stamp)
|
||||
widget.stamp = GObject.timeout_add(250, _work)
|
||||
|
||||
|
||||
+42
-3
@@ -74,11 +74,10 @@ from entropy.output import darkgreen, brown, darkred, red, blue
|
||||
|
||||
import entropy.tools
|
||||
|
||||
|
||||
class RigoServiceController(GObject.Object):
|
||||
|
||||
"""
|
||||
This is the Rigo Application frontend to Rigo Daemon.
|
||||
This is the Rigo Application frontend to RigoDaemon.
|
||||
Handles privileged requests on our behalf.
|
||||
"""
|
||||
|
||||
@@ -175,6 +174,7 @@ class RigoServiceController(GObject.Object):
|
||||
_RESOURCES_UNLOCK_REQUEST_SIGNAL = "resources_unlock_request"
|
||||
_RESOURCES_LOCK_REQUEST_SIGNAL = "resources_lock_request"
|
||||
_ACTIVITY_STARTED_SIGNAL = "activity_started"
|
||||
_ACTIVITY_PROGRESS_SIGNAL = "activity_progress"
|
||||
_ACTIVITY_COMPLETED_SIGNAL = "activity_completed"
|
||||
_PROCESSING_APPLICATION_SIGNAL = "processing_application"
|
||||
_APPLICATION_PROCESSED_SIGNAL = "application_processed"
|
||||
@@ -201,8 +201,10 @@ class RigoServiceController(GObject.Object):
|
||||
self._registered_signals = {}
|
||||
self._registered_signals_mutex = Lock()
|
||||
|
||||
self._local_transactions = {}
|
||||
self._local_activity = LocalActivityStates.READY
|
||||
self._local_activity_mutex = Lock()
|
||||
self._daemon_activity_progress = 0
|
||||
|
||||
self._please_wait_box = None
|
||||
self._please_wait_mutex = Lock()
|
||||
@@ -320,6 +322,12 @@ class RigoServiceController(GObject.Object):
|
||||
"""
|
||||
return self._local_activity
|
||||
|
||||
def local_transactions(self):
|
||||
"""
|
||||
Return the current local transaction state mapping.
|
||||
"""
|
||||
return self._local_transactions
|
||||
|
||||
@property
|
||||
def repositories_lock(self):
|
||||
"""
|
||||
@@ -388,6 +396,13 @@ class RigoServiceController(GObject.Object):
|
||||
self._activity_started_signal,
|
||||
dbus_interface=self.DBUS_INTERFACE)
|
||||
|
||||
# RigoDaemon is telling us the activity
|
||||
# progress
|
||||
self.__entropy_bus.connect_to_signal(
|
||||
self._ACTIVITY_PROGRESS_SIGNAL,
|
||||
self._activity_progress_signal,
|
||||
dbus_interface=self.DBUS_INTERFACE)
|
||||
|
||||
# RigoDaemon is telling us that an activity
|
||||
# has been completed
|
||||
self.__entropy_bus.connect_to_signal(
|
||||
@@ -776,6 +791,18 @@ class RigoServiceController(GObject.Object):
|
||||
# reset please wait notification then
|
||||
self._please_wait(None)
|
||||
|
||||
def _activity_progress_signal(self, activity, progress):
|
||||
"""
|
||||
RigoDaemon is telling us the currently running activity
|
||||
progress.
|
||||
"""
|
||||
const_debug_write(
|
||||
__name__,
|
||||
"_activity_progress_signal: "
|
||||
"called, with remote activity: %s, val: %i" % (
|
||||
activity, progress,))
|
||||
self._daemon_activity_progress = progress
|
||||
|
||||
def _activity_completed_signal(self, activity, success):
|
||||
"""
|
||||
RigoDaemon is telling us that the scheduled activity,
|
||||
@@ -827,6 +854,17 @@ class RigoServiceController(GObject.Object):
|
||||
self._entropy_bus,
|
||||
dbus_interface=self.DBUS_INTERFACE).action_queue_length()
|
||||
|
||||
def action(self, app):
|
||||
"""
|
||||
Return Application transaction state (RigoDaemon.AppAction enum
|
||||
value).
|
||||
"""
|
||||
package_id, repository_id = app.get_details().pkg
|
||||
return dbus.Interface(
|
||||
self._entropy_bus,
|
||||
dbus_interface=self.DBUS_INTERFACE).action(
|
||||
package_id, repository_id)
|
||||
|
||||
def exclusive(self):
|
||||
"""
|
||||
Return whether RigoDaemon is running in with
|
||||
@@ -2108,7 +2146,8 @@ class Rigo(Gtk.Application):
|
||||
self._work_view.set_name("rigo-view")
|
||||
|
||||
self._app_view_c = ApplicationViewController(
|
||||
self._entropy, self._entropy_ws, self._builder)
|
||||
self._entropy, self._entropy_ws, self._service,
|
||||
self._builder)
|
||||
|
||||
self._view = AppTreeView(
|
||||
self._entropy, self._service, self._app_view_c, icons,
|
||||
|
||||
Reference in New Issue
Block a user