18
18
#
19
19
20
20
import subprocess
21
- from PyQt6 import QtWidgets , QtCore # pylint: disable=import-error
21
+ from PyQt6 import QtWidgets , QtCore , QtGui # pylint: disable=import-error
22
22
from qubesadmin import exc
23
+ from qubesmanager .utils import tint_qimage
24
+ from os import path
23
25
24
- # TODO description in tooltip
25
- # TODO icon
26
26
# pylint: disable=too-few-public-methods
27
+
28
+
27
29
class AppListWidgetItem (QtWidgets .QListWidgetItem ):
28
30
def __init__ (self , name , ident , tooltip = None , parent = None ):
29
31
super ().__init__ (name , parent )
@@ -39,38 +41,48 @@ def __init__(self, name, ident, tooltip=None, parent=None):
39
41
40
42
@classmethod
41
43
def from_line (cls , line ):
42
- ident , name , comment = line .split ('|' , maxsplit = 3 )
44
+ ident , name , comment = line .split ("|" , maxsplit = 3 )
43
45
return cls (name = name , ident = ident , tooltip = comment )
44
46
45
47
@classmethod
46
48
def from_ident (cls , ident ):
47
- name = 'Application missing in template! ({})' .format (ident )
48
- comment = 'The listed application was available at some point to ' \
49
- 'this qube, but not any more. The most likely cause is ' \
50
- 'template change. Install the application in the template ' \
51
- 'if you want to restore it.'
49
+ name = "Application missing in template! ({})" .format (ident )
50
+ comment = (
51
+ "The listed application was available at some point to "
52
+ "this qube, but not any more. The most likely cause is "
53
+ "template change. Install the application in the template "
54
+ "if you want to restore it."
55
+ )
52
56
return cls (name = name , ident = ident , tooltip = comment )
53
57
54
58
55
59
class AppmenuSelectManager :
56
60
def __init__ (self , vm , apps_multiselect ):
57
61
self .vm = vm
58
- self .app_list = apps_multiselect # this is a multiselect wiget
62
+ self .app_list = apps_multiselect # this is a multiselect wiget
59
63
self .whitelisted = None
60
64
self .has_missing = False
61
65
self .fill_apps_list (template = None )
62
66
63
67
def fill_apps_list (self , template = None ):
64
68
try :
65
- self .whitelisted = [line for line in subprocess .check_output (
66
- ['qvm-appmenus' , '--get-whitelist' , self .vm .name ]
67
- ).decode ().strip ().split ('\n ' ) if line ]
69
+ self .whitelisted = [
70
+ line
71
+ for line in subprocess .check_output (
72
+ ["qvm-appmenus" , "--get-whitelist" , self .vm .name ]
73
+ )
74
+ .decode ()
75
+ .strip ()
76
+ .split ("\n " )
77
+ if line
78
+ ]
68
79
except exc .QubesException :
69
80
self .whitelisted = []
70
81
71
82
currently_selected = [
72
83
self .app_list .selected_list .item (i ).whatsThis ()
73
- for i in range (self .app_list .selected_list .count ())]
84
+ for i in range (self .app_list .selected_list .count ())
85
+ ]
74
86
75
87
whitelist = set (self .whitelisted + currently_selected )
76
88
@@ -81,18 +93,61 @@ def fill_apps_list(self, template=None):
81
93
82
94
self .app_list .clear ()
83
95
84
- command = ['qvm-appmenus' , '--get-available' ,
85
- '--i-understand-format-is-unstable' , '--file-field' ,
86
- 'Comment' ]
96
+ command = [
97
+ "qvm-appmenus" ,
98
+ "--get-available" ,
99
+ "--i-understand-format-is-unstable" ,
100
+ "--file-field" ,
101
+ "Comment" ,
102
+ "--file-field" ,
103
+ "Icon" ,
104
+ ]
87
105
if template :
88
- command .extend ([' --template' , template .name ])
106
+ command .extend ([" --template" , template .name ])
89
107
command .append (self .vm .name )
90
108
109
+ if not hasattr (self .vm , "template" ):
110
+ # TemplateVMs and StandaloneVMs
111
+ main_template = self .vm .name
112
+ elif not hasattr (self .vm .template , "template" ):
113
+ # AppVMs
114
+ main_template = self .vm .template .name
115
+ else :
116
+ # DispVMs
117
+ main_template = self .vm .template .template .name
118
+
119
+ template_icons_path = path .join (
120
+ path .expanduser ("~" ),
121
+ ".local" ,
122
+ "share" ,
123
+ "qubes-appmenus" ,
124
+ f"{ main_template } " ,
125
+ "apps.tempicons" ,
126
+ )
127
+
91
128
try :
92
- available_appmenus = [
93
- AppListWidgetItem .from_line (line )
94
- for line in subprocess .check_output (
95
- command ).decode ().splitlines ()]
129
+ available_appmenus = []
130
+ for line in subprocess .check_output (command ).decode ().splitlines ():
131
+ ident , name , comment , icon_path = line .split ("|" , maxsplit = 4 )
132
+ app_item = AppListWidgetItem .from_line (
133
+ "|" .join ([ident , name , comment ])
134
+ )
135
+ icon_path = icon_path .replace (
136
+ "%VMDIR%/apps.icons" , template_icons_path
137
+ )
138
+ if path .exists (icon_path ):
139
+ icon = QtGui .QIcon (icon_path )
140
+ qpixmap = icon .pixmap (QtCore .QSize (512 , 512 ))
141
+ qimage = QtGui .QImage (qpixmap )
142
+ qimage = tint_qimage (qimage , self .vm .label .color )
143
+ qpixmap = QtGui .QPixmap (qimage )
144
+ icon = QtGui .QIcon (qpixmap )
145
+ else :
146
+ # for `qubes-start.desktop` & missing icons
147
+ icon = QtGui .QIcon .fromTheme (self .vm .icon )
148
+ app_item .setIcon (icon )
149
+ available_appmenus .append (app_item )
150
+
96
151
except exc .QubesException :
97
152
available_appmenus = []
98
153
@@ -113,16 +168,21 @@ def fill_apps_list(self, template=None):
113
168
self .app_list .selected_list .sortItems ()
114
169
115
170
def save_appmenu_select_changes (self ):
116
- new_whitelisted = [self .app_list .selected_list .item (i ).whatsThis ()
117
- for i in range (self .app_list .selected_list .count ())]
171
+ new_whitelisted = [
172
+ self .app_list .selected_list .item (i ).whatsThis ()
173
+ for i in range (self .app_list .selected_list .count ())
174
+ ]
118
175
119
176
if set (new_whitelisted ) == set (self .whitelisted ):
120
177
return False
121
178
122
179
try :
123
- self .vm .features [' menu-items' ] = " " .join (new_whitelisted )
180
+ self .vm .features [" menu-items" ] = " " .join (new_whitelisted )
124
181
except exc .QubesException as ex :
125
- raise RuntimeError (QtCore .QCoreApplication .translate (
126
- "exception" , 'Failed to set menu items' )) from ex
182
+ raise RuntimeError (
183
+ QtCore .QCoreApplication .translate (
184
+ "exception" , "Failed to set menu items"
185
+ )
186
+ ) from ex
127
187
128
188
return True
0 commit comments