Skip to content

Commit 2e385a3

Browse files
committed
Added root terminal to Domains tray icon menu
1 parent 3d5af8f commit 2e385a3

File tree

1 file changed

+78
-6
lines changed

1 file changed

+78
-6
lines changed

qui/tray/domains.py

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import qui.utils
1919

2020
gi.require_version("Gtk", "3.0") # isort:skip
21-
from gi.repository import Gio, Gtk, GLib, GdkPixbuf # isort:skip
21+
from gi.repository import Gdk, Gio, Gtk, GLib, GdkPixbuf, GObject # isort:skip
2222

2323
import gbulb
2424

@@ -108,7 +108,11 @@ def __init__(self, label, img=None, icon_cache=None, icon_name=None):
108108
box.pack_start(placeholder, False, False, 0)
109109

110110
# Add a label to the menu item
111-
label_widget = Gtk.Label(label=label, xalign=0)
111+
label_widget = label
112+
if isinstance(label_widget, Gtk.Label):
113+
label_widget.set_xalign(0)
114+
else:
115+
label_widget = Gtk.Label(label=label, xalign=0)
112116
box.pack_start(label_widget, True, True, 0)
113117

114118
# Add the box to the menu item
@@ -289,17 +293,45 @@ async def perform_action(self):
289293
class RunTerminalItem(VMActionMenuItem):
290294
"""Run Terminal menu Item. When activated runs a terminal emulator."""
291295

292-
def __init__(self, vm, icon_cache):
296+
__gsignals__ = {
297+
"set-terminal-user-root": (
298+
GObject.SignalFlags.RUN_FIRST,
299+
GObject.TYPE_NONE,
300+
(bool,),
301+
),
302+
}
303+
304+
def __init__(self, vm, icon_cache, as_root=False):
305+
label = Gtk.Label(label=RunTerminalItem.dynamic_label(as_root))
293306
super().__init__(
294307
vm,
295-
label=_("Run Terminal"),
308+
label=label,
296309
icon_cache=icon_cache,
297310
icon_name="terminal",
298311
)
312+
self.as_root = as_root
313+
self.label = label
314+
self.connect("set-terminal-user-root", self.set_as_root)
315+
316+
@staticmethod
317+
def dynamic_label(as_root):
318+
if as_root:
319+
return _("Run Root Terminal")
320+
return _("Run Terminal")
321+
322+
def set_as_root(self, _item, as_root):
323+
self.as_root = as_root
324+
self.label.set_text(RunTerminalItem.dynamic_label(as_root))
299325

300326
async def perform_action(self):
327+
service_args = {}
328+
if self.as_root:
329+
service_args["user"] = "root"
301330
try:
302-
self.vm.run_service("qubes.StartApp+qubes-run-terminal")
331+
self.vm.run_service(
332+
"qubes.StartApp+qubes-run-terminal",
333+
**service_args
334+
)
303335
except exc.QubesException as ex:
304336
show_error(
305337
_("Error starting terminal"),
@@ -361,7 +393,7 @@ def __init__(self, vm, app, icon_cache):
361393
self.app = app
362394

363395
self.add(OpenFileManagerItem(self.vm, icon_cache))
364-
self.add(RunTerminalItem(self.vm, icon_cache))
396+
self.add(RunTerminalItem(self.vm, icon_cache, as_root=app.terminal_as_root))
365397
self.add(PreferencesItem(self.vm, icon_cache))
366398
self.add(PauseItem(self.vm, icon_cache))
367399
self.add(ShutdownItem(self.vm, icon_cache))
@@ -562,6 +594,8 @@ def _set_submenu(self, state):
562594
submenu = PausedMenu(self.vm, self.icon_cache)
563595
else:
564596
submenu = DebugMenu(self.vm, self.icon_cache)
597+
submenu.connect("key-press-event", self.app.key_event)
598+
submenu.connect("key-release-event", self.app.key_event)
565599
# This is a workaround for a bug in Gtk which occurs when a
566600
# submenu is replaced while it is open.
567601
# see https://gitlab.gnome.org/GNOME/gtk/issues/885
@@ -637,6 +671,8 @@ def __init__(self, app_name, qapp, dispatcher, stats_dispatcher):
637671

638672
self.tray_menu = Gtk.Menu()
639673
self.tray_menu.set_reserve_toggle_size(False)
674+
self.tray_menu.connect("key-press-event", self.key_event)
675+
self.tray_menu.connect("key-release-event", self.key_event)
640676

641677
self.icon_cache = IconCache()
642678

@@ -704,6 +740,7 @@ def register_events(self):
704740
self.stats_dispatcher.add_handler("vm-stats", self.update_stats)
705741

706742
def show_menu(self, _unused, event):
743+
self.terminal_as_root = False
707744
self.tray_menu.popup_at_pointer(event) # None means current event
708745

709746
def emit_notification(self, vm, event, **kwargs):
@@ -1055,6 +1092,41 @@ def _disconnect_signals(self, _event):
10551092

10561093
self.stats_dispatcher.remove_handler("vm-stats", self.update_stats)
10571094

1095+
@property
1096+
def terminal_as_root(self):
1097+
try:
1098+
return self._terminal_as_root
1099+
except AttributeError:
1100+
self._terminal_as_root = False
1101+
return self.terminal_as_root
1102+
1103+
@terminal_as_root.setter
1104+
def terminal_as_root(self, as_root):
1105+
if as_root == self.terminal_as_root:
1106+
return
1107+
1108+
self._terminal_as_root = as_root
1109+
for item in self.menu_items.values():
1110+
if item.vm:
1111+
submenu = item.get_submenu()
1112+
if submenu is None:
1113+
continue
1114+
1115+
def do_emit(child):
1116+
try:
1117+
child.emit("set-terminal-user-root", as_root)
1118+
except Exception: # pylint: disable=broad-except
1119+
pass
1120+
1121+
submenu.foreach(do_emit)
1122+
1123+
def key_event(self, _unused, event):
1124+
if event.keyval in [Gdk.KEY_Shift_L, Gdk.KEY_Shift_R]:
1125+
if event.type == Gdk.EventType.KEY_PRESS:
1126+
self.terminal_as_root = True
1127+
elif event.type == Gdk.EventType.KEY_RELEASE:
1128+
self.terminal_as_root = False
1129+
10581130

10591131
def main():
10601132
"""main function"""

0 commit comments

Comments
 (0)