Skip to content

Commit a84146b

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

1 file changed

Lines changed: 82 additions & 6 deletions

File tree

qui/tray/domains.py

Lines changed: 82 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,11 @@ 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(
397+
self.vm,
398+
icon_cache,
399+
as_root=app.terminal_as_root
400+
))
365401
self.add(PreferencesItem(self.vm, icon_cache))
366402
self.add(PauseItem(self.vm, icon_cache))
367403
self.add(ShutdownItem(self.vm, icon_cache))
@@ -562,6 +598,8 @@ def _set_submenu(self, state):
562598
submenu = PausedMenu(self.vm, self.icon_cache)
563599
else:
564600
submenu = DebugMenu(self.vm, self.icon_cache)
601+
submenu.connect("key-press-event", self.app.key_event)
602+
submenu.connect("key-release-event", self.app.key_event)
565603
# This is a workaround for a bug in Gtk which occurs when a
566604
# submenu is replaced while it is open.
567605
# see https://gitlab.gnome.org/GNOME/gtk/issues/885
@@ -637,6 +675,8 @@ def __init__(self, app_name, qapp, dispatcher, stats_dispatcher):
637675

638676
self.tray_menu = Gtk.Menu()
639677
self.tray_menu.set_reserve_toggle_size(False)
678+
self.tray_menu.connect("key-press-event", self.key_event)
679+
self.tray_menu.connect("key-release-event", self.key_event)
640680

641681
self.icon_cache = IconCache()
642682

@@ -704,6 +744,7 @@ def register_events(self):
704744
self.stats_dispatcher.add_handler("vm-stats", self.update_stats)
705745

706746
def show_menu(self, _unused, event):
747+
self.terminal_as_root = False
707748
self.tray_menu.popup_at_pointer(event) # None means current event
708749

709750
def emit_notification(self, vm, event, **kwargs):
@@ -1055,6 +1096,41 @@ def _disconnect_signals(self, _event):
10551096

10561097
self.stats_dispatcher.remove_handler("vm-stats", self.update_stats)
10571098

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

10591135
def main():
10601136
"""main function"""

0 commit comments

Comments
 (0)