1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import time
20 import gobject
21 import gtk
22 import gtk.gdk
23 import pango
24 import util
25 import userprofile
26 import protosession
27 import changeswindow
28 import sessionwidget
29 import saveconfirm
30 import aboutdialog
31 import debuglog
32 import errors
33 from lockdownappliersabayon import LockdownApplierSabayon
34 from Pessulus import maindialog as lockdowndialog
35 from config import *
36
37 _ui_string = '''
38 <ui>
39 <menubar name="Menubar">
40 <menu action="ProfileMenu">
41 <menuitem action="Save"/>
42 <separator/>
43 <menuitem action="Quit"/>
44 </menu>
45 <menu action="EditMenu">
46 <menuitem action="Changes"/>
47 <menuitem action="Lockdown"/>
48 <menuitem action="EnforceMandatory"/>
49 </menu>
50 <menu action="HelpMenu">
51 <menuitem action="Contents"/>
52 <menuitem action="About"/>
53 </menu>
54 </menubar>
55 </ui>
56 '''
57
60
62 __gsignals__ = {
63 "changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (userprofile.ProfileChange, ))
64 }
65
66 (
67 COLUMN_CHANGE,
68 COLUMN_IGNORE,
69 COLUMN_MANDATORY,
70 COLUMN_LOCK_PIXBUF,
71 COLUMN_DESCRIPTION
72 ) = range (5)
73
75 gtk.ListStore.__init__ (self, userprofile.ProfileChange, bool, bool, gtk.gdk.Pixbuf, str)
76
77 icon_theme = gtk.icon_theme_get_default ()
78
79 self.locked_pixbuf = icon_theme.load_icon ("stock_lock", 22,
80 gtk.ICON_LOOKUP_FORCE_SVG)
81 self.unlocked_pixbuf = icon_theme.load_icon ("stock_lock-open", 22,
82 gtk.ICON_LOOKUP_FORCE_SVG)
83
84 self.profile = profile
85 self.profile.connect ("changed", self.handle_profile_change)
86
87
88 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_ADMIN_TOOL)
90 default_mandatory = False
91 ignore = new_change.get_ignore_default ()
92 iter = self.find (new_change.get_source (), new_change.get_id ())
93 old_change = None
94 if iter:
95 ignore = self[iter][self.COLUMN_IGNORE]
96 default_mandatory = self[iter][self.COLUMN_MANDATORY]
97 old_change = self[iter][self.COLUMN_CHANGE]
98 self.remove (iter)
99
100 mandatory = new_change.get_mandatory ()
101 if mandatory == None:
102 mandatory = default_mandatory
103
104 if mandatory:
105 lock_pixbuf = self.locked_pixbuf
106 else:
107 lock_pixbuf = self.unlocked_pixbuf
108
109 discard_change = False
110 if old_change:
111 discard_change = new_change.merge_old_change (old_change)
112
113 if not discard_change:
114 row = self.prepend ()
115 self.set (row,
116 self.COLUMN_CHANGE, new_change,
117 self.COLUMN_IGNORE, ignore,
118 self.COLUMN_MANDATORY, mandatory,
119 self.COLUMN_LOCK_PIXBUF, lock_pixbuf,
120 self.COLUMN_DESCRIPTION, new_change.get_short_description ())
121 self.emit ("changed", new_change)
122
124 gtk.ListStore.clear (self)
125 self.emit ("changed", None)
126
127 - def find (self, source, id):
128 iter = self.get_iter_first ()
129 while iter:
130 next = self.iter_next (iter)
131 change = self[iter][self.COLUMN_CHANGE]
132 if change.get_source () == source and \
133 change.get_id () == id:
134 return iter
135 iter = next
136 return None
137
138
139 gobject.type_register (ProfileChangesModel)
140
142 - def __init__ (self, profile_name, profile_path, display_number):
143 self.profile_name = profile_name
144 self.profile_path = profile_path
145 self.display_number = display_number
146
147 self.profile = userprofile.UserProfile (profile_path)
148
149 self.changes_model = ProfileChangesModel (self.profile)
150 self.changes_model.connect ("changed", self.__changes_model_changed)
151 self.changes_window = None
152 self.lockdown_window = None
153
154 self.last_save_time = 0
155
156 self.window = gtk.Window ()
157 self.window.set_title (_("Editing profile %s")%profile_name)
158 self.window.set_icon_name ("sabayon")
159 self.window.connect ("delete-event",
160 self.__handle_delete_event);
161
162 self.box = gtk.VBox ()
163 self.window.add (self.box)
164 self.box.show ()
165
166 self.__setup_menus ()
167 self.__setup_session ()
168 self.__setup_statusbar ()
169
170 self.__set_needs_saving (False)
171
172
173 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_ADMIN_TOOL)
175 self.box.pack_start (widget, False, False, 0)
176
178 actions = [
179 ("ProfileMenu", None, _("_Profile")),
180 ("Save", gtk.STOCK_SAVE, _("_Save"), "<control>S", _("Save profile"), self.__handle_save),
181 ("Quit", gtk.STOCK_QUIT, _("_Quit"), "<control>Q", _("Close the current window"), self.__handle_quit),
182 ("EditMenu", None, _("_Edit")),
183 ("Changes", gtk.STOCK_EDIT, _("_Changes"), "<control>H", _("Edit changes"), self.__handle_edit),
184 ("Lockdown", None, _("_Lockdown"),"<control>L", _("Edit Lockdown settings"), self.__handle_lockdown),
185 ("HelpMenu", None, _("_Help")),
186 ("Contents", gtk.STOCK_ABOUT, _("_Contents"),None, _("Help Contents"), self.__handle_help),
187 ("About", gtk.STOCK_ABOUT, _("_About"), None, _("About Sabayon"), self.__handle_about),
188 ]
189 toggle_actions = [
190 ("EnforceMandatory", None, _("Enforce Mandatory"), None, _("Enforce mandatory settings in the editing session"), self.__handle_enforce_mandatory, True),
191 ]
192 action_group = gtk.ActionGroup ("WindowActions")
193 action_group.add_actions (actions)
194 action_group.add_toggle_actions (toggle_actions)
195
196 self.ui_manager = gtk.UIManager ()
197 self.ui_manager.insert_action_group (action_group, 0)
198 self.ui_manager.connect ("add-widget", self.__add_widget)
199 self.ui_manager.add_ui_from_string (_ui_string)
200 self.ui_manager.ensure_update ()
201
202 self.window.add_accel_group (self.ui_manager.get_accel_group ())
203
204 self.save_action = action_group.get_action ("Save")
205
207 if needs_saving:
208 if not self.last_save_time:
209 self.last_save_time = int (time.time ())
210 self.save_action.set_sensitive (True)
211 else:
212 self.last_save_time = 0
213 self.save_action.set_sensitive (False)
214
215 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_ADMIN_TOOL)
218
251
253 if self.last_save_time:
254 dialog = saveconfirm.SaveConfirmationAlert (self.window,
255 self.profile_name,
256 time.time () - self.last_save_time)
257 response = dialog.run ()
258 dialog.destroy ()
259
260 if response == gtk.RESPONSE_CANCEL or \
261 response == gtk.RESPONSE_DELETE_EVENT:
262 return False
263 if response == gtk.RESPONSE_YES:
264 self.__do_save ()
265
266 return True
267
268 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
271
272 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
276
277 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
280
281 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
283 try:
284 gtk.show_uri (None, "ghelp:sabayon", gtk.get_current_event_time())
285 except gobject.GError, e:
286 pass
287
288 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
291
292 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
294 if not self.changes_window:
295 self.changes_window = changeswindow.ChangesWindow (self.changes_model,
296 self.profile_name,
297 self.window)
298 self.changes_window.window.connect ("delete-event",
299 gtk.Widget.hide_on_delete)
300 self.changes_window.window.present ()
301
302 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
304 if not self.lockdown_window:
305 debuglog.uprint ("Creating new Lockdown window")
306 applier = LockdownApplierSabayon (self.profile, self.changes_model)
307 self.lockdown_window = lockdowndialog.PessulusMainDialog (applier, False)
308 self.lockdown_window.window.set_title (_("Lockdown settings for %s")%self.profile_name)
309 else:
310 debuglog.uprint ("Presenting existing Lockdown window")
311
312 self.lockdown_window.window.present ()
313
314 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_USER)
319
320 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_ADMIN_TOOL)
322 self.window.destroy ()
323
324 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_ADMIN_TOOL)
326 dprint ("Session widget mapped; starting prototype session")
327 self.session_widget.disconnect (self.mapped_handler_id)
328 self.mapped_handler_id = 0
329 self.session.connect ("finished", self.__session_finished)
330 self.session.start (str (self.session_widget.session_window.xid))
331 return False
332
334 self.session = protosession.ProtoSession (self.profile_name, self.display_number)
335
336 try:
337 self.session.apply_profile ()
338 except errors.RecoverableApplyErrorException, e:
339 errors_log_recoverable_exception (e)
340 dialog = gtk.MessageDialog (parent = None,
341 flags = gtk.DIALOG_MODAL,
342 type = gtk.MESSAGE_ERROR,
343 buttons = gtk.BUTTONS_NONE,
344 message_format = _("There was a recoverable error while applying the "
345 "user profile '%s'. You can report this error now "
346 "or try to continue editing the user profile."))
347 (REPORT, CONTINUE) = range (2)
348 dialog.add_button (_("_Report this error"), REPORT)
349 dialog.add_button (_("_Continue editing"), CONTINUE)
350 response = dialog.run ()
351 dialog.destroy ()
352
353 if response == REPORT:
354 raise
355
356 except errors.FatalApplyErrorException, e:
357 raise
358
359
360 self.profile.start_monitoring ()
361 screen = gtk.gdk.screen_get_default ()
362 width = (screen.get_width () * 3) / 4
363 height = (screen.get_height () * 3) / 4
364
365 dprint ("Creating %dx%d session widget", width, height)
366
367 self.session_widget = sessionwidget.SessionWidget (width, height)
368 self.box.pack_start (self.session_widget, True, True)
369 self.mapped_handler_id = self.session_widget.connect ("map-event", self.__session_mapped)
370 self.session_widget.show ()
371
372 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_ADMIN_TOOL)
374 if change:
375 self.statusbar.pop (self.status_context_id)
376 self.statusbar.push (self.status_context_id,
377 change.get_short_description ())
378
379 @errors.checked_callback (debuglog.DEBUG_LOG_DOMAIN_ADMIN_TOOL)
381 if event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED:
382 if event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED:
383 self.statusbar.set_has_resize_grip (False)
384 else:
385 self.statusbar.set_has_resize_grip (True)
386
388 self.statusbar = gtk.Statusbar ()
389 self.box.pack_start (self.statusbar, False, False)
390 self.statusbar.show ()
391
392 self.status_context_id = self.statusbar.get_context_id ("sabayon-change")
393
394 self.changes_model.connect ("changed", self.__update_statusbar)
395
396 self.window.connect ("window-state-event", self.__update_resize_grip)
397