@@ -95,13 +95,21 @@ def __init__(self, args):
95
95
self .type = args .type
96
96
self .uuid = args .uuid
97
97
self .tab = 0
98
+ self .instance_info = []
98
99
self .instance_id = str (args .id )
99
100
if args .tab is not None :
100
101
self .tab = int (args .tab )
101
102
102
103
self .selected_instance = None
103
104
self .gsettings = Gio .Settings .new ("org.cinnamon" )
105
+ self .monitors = {}
106
+ self .g_directories = []
104
107
self .custom_modules = {}
108
+ if self .type == "applet" : changed_key = "enabled-applets"
109
+ elif self .type == "desklet" : changed_key = "enabled-desklets"
110
+ else : changed_key = None
111
+ if changed_key :
112
+ self .gsettings .connect ("changed::" + changed_key , lambda * args : self .on_enabled_xlets_changed (changed_key , * args ))
105
113
106
114
self .load_xlet_data ()
107
115
self .build_window ()
@@ -128,7 +136,7 @@ def _on_proxy_ready (self, obj, result, data=None):
128
136
proxy = None
129
137
130
138
if proxy :
131
- proxy . highlightXlet ( '(ssb)' , self .uuid , self . selected_instance [ "id" ] , True )
139
+ self . highlight_xlet ( self .selected_instance , True )
132
140
133
141
def load_xlet_data (self ):
134
142
self .xlet_dir = "/usr/share/cinnamon/%ss/%s" % (self .type , self .uuid )
@@ -242,18 +250,22 @@ def check_sizing(widget, data=None):
242
250
self .next_button .connect ("clicked" , self .next_instance )
243
251
244
252
def load_instances (self ):
245
- self .instance_info = []
246
253
path = Path (os .path .join (settings_dir , self .uuid ))
247
254
old_path = Path ("%s/.cinnamon/configs/%s" % (home , self .uuid ))
248
- instances = 0
255
+ for p in path , old_path :
256
+ if not p .exists (): continue
257
+ self .g_directories .append (Gio .File .new_for_path (str (p )))
258
+
249
259
new_items = os .listdir (path ) if path .exists () else []
250
260
old_items = os .listdir (old_path ) if old_path .exists () else []
251
261
dir_items = sorted (new_items + old_items )
262
+
252
263
try :
253
264
multi_instance = int (self .xlet_meta ["max-instances" ]) != 1
254
265
except (KeyError , ValueError ):
255
266
multi_instance = False
256
267
268
+ enabled = [x .split (":" ) for x in self .gsettings .get_strv ('enabled-%ss' % self .type )]
257
269
for item in dir_items :
258
270
# ignore anything that isn't json
259
271
if item [- 5 :] != ".json" :
@@ -271,66 +283,82 @@ def load_instances(self):
271
283
continue # multi-instance should have file names of the form [instance-id].json
272
284
273
285
instance_exists = False
274
- enabled = self .gsettings .get_strv ('enabled-%ss' % self .type )
275
286
for definition in enabled :
276
- if self .uuid in definition and instance_id in definition . split ( ':' ) :
287
+ if self .uuid in definition and instance_id in definition :
277
288
instance_exists = True
278
289
break
279
290
280
291
if not instance_exists :
281
292
continue
282
293
283
- settings = JSONSettingsHandler (os .path .join (path if item in new_items else old_path , item ), self .notify_dbus )
284
- settings .instance_id = instance_id
285
- instance_box = Gtk .Box (orientation = Gtk .Orientation .VERTICAL )
286
- self .instance_stack .add_named (instance_box , instance_id )
287
-
288
- info = {"settings" : settings , "id" : instance_id }
289
- self .instance_info .append (info )
294
+ config_path = os .path .join (path if item in new_items else old_path , item )
295
+ self .create_settings_page (config_path )
296
+
297
+ if not self .instance_info :
298
+ print (f"No instances were found for { self .uuid } . Exiting..." )
299
+ sys .exit ()
300
+
301
+ self .next_button .set_no_show_all (True )
302
+ self .prev_button .set_no_show_all (True )
303
+ self .show_prev_next_buttons () if self .has_multiple_instances () else self .hide_prev_next_buttons ()
304
+
305
+ def create_settings_page (self , config_path ):
306
+ instance_id = os .path .basename (config_path )[:- 5 ]
307
+ if self .instance_stack .get_child_by_name (instance_id ) is not None : return
308
+ settings = JSONSettingsHandler (config_path , self .notify_dbus )
309
+ settings .instance_id = instance_id
310
+ instance_box = Gtk .Box (orientation = Gtk .Orientation .VERTICAL )
311
+ self .instance_stack .add_named (instance_box , instance_id )
312
+ info = {"settings" : settings , "id" : instance_id }
313
+ self .instance_info .append (info )
314
+ settings_map = settings .get_settings ()
315
+ first_key = next (iter (settings_map .values ()))
290
316
291
- settings_map = settings .get_settings ()
292
- first_key = next (iter (settings_map .values ()))
317
+ try :
318
+ for setting in settings_map :
319
+ if setting == "__md5__" :
320
+ continue
321
+ for key in settings_map [setting ]:
322
+ if key in ("description" , "tooltip" , "units" ):
323
+ try :
324
+ settings_map [setting ][key ] = translate (self .uuid , settings_map [setting ][key ])
325
+ except (KeyError , ValueError ):
326
+ traceback .print_exc ()
327
+ elif key in "options" :
328
+ new_opt_data = collections .OrderedDict ()
329
+ opt_data = settings_map [setting ][key ]
330
+ for option in opt_data :
331
+ if opt_data [option ] == "custom" :
332
+ continue
333
+ new_opt_data [translate (self .uuid , option )] = opt_data [option ]
334
+ settings_map [setting ][key ] = new_opt_data
335
+ elif key in "columns" :
336
+ columns_data = settings_map [setting ][key ]
337
+ for column in columns_data :
338
+ column ["title" ] = translate (self .uuid , column ["title" ])
339
+ finally :
340
+ # if a layout is not explicitly defined, generate the settings
341
+ # widgets based on the order they occur
342
+ if first_key ["type" ] == "layout" :
343
+ self .build_with_layout (settings_map , info , instance_box , first_key )
344
+ else :
345
+ self .build_from_order (settings_map , info , instance_box , first_key )
293
346
294
- try :
295
- for setting in settings_map :
296
- if setting == "__md5__" :
297
- continue
298
- for key in settings_map [setting ]:
299
- if key in ("description" , "tooltip" , "units" ):
300
- try :
301
- settings_map [setting ][key ] = translate (self .uuid , settings_map [setting ][key ])
302
- except (KeyError , ValueError ):
303
- traceback .print_exc ()
304
- elif key in "options" :
305
- new_opt_data = collections .OrderedDict ()
306
- opt_data = settings_map [setting ][key ]
307
- for option in opt_data :
308
- if opt_data [option ] == "custom" :
309
- continue
310
- new_opt_data [translate (self .uuid , option )] = opt_data [option ]
311
- settings_map [setting ][key ] = new_opt_data
312
- elif key in "columns" :
313
- columns_data = settings_map [setting ][key ]
314
- for column in columns_data :
315
- column ["title" ] = translate (self .uuid , column ["title" ])
316
- finally :
317
- # if a layout is not explicitly defined, generate the settings
318
- # widgets based on the order they occur
319
- if first_key ["type" ] == "layout" :
320
- self .build_with_layout (settings_map , info , instance_box , first_key )
321
- else :
322
- self .build_from_order (settings_map , info , instance_box , first_key )
347
+ if self .selected_instance is None :
348
+ self .selected_instance = info
349
+ if "stack" in info :
350
+ self .stack_switcher .set_stack (info ["stack" ])
323
351
324
- if self .selected_instance is None :
325
- self .selected_instance = info
326
- if "stack" in info :
327
- self .stack_switcher .set_stack (info ["stack" ])
352
+ def has_multiple_instances (self ):
353
+ return len (self .instance_info ) > 1
328
354
329
- instances += 1
355
+ def hide_prev_next_buttons (self ):
356
+ self .prev_button .hide ()
357
+ self .next_button .hide ()
330
358
331
- if instances < 2 :
332
- self .prev_button .set_no_show_all ( True )
333
- self .next_button .set_no_show_all ( True )
359
+ def show_prev_next_buttons ( self ) :
360
+ self .prev_button .show ( )
361
+ self .next_button .show ( )
334
362
335
363
def build_with_layout (self , settings_map , info , box , first_key ):
336
364
layout = first_key
@@ -460,26 +488,95 @@ def set_instance(self, info):
460
488
else :
461
489
info ["stack" ].set_visible_child (children [0 ])
462
490
if proxy :
463
- proxy .highlightXlet ('(ssb)' , self .uuid , self .selected_instance ["id" ], False )
464
- proxy .highlightXlet ('(ssb)' , self .uuid , info ["id" ], True )
491
+ old_info = self .selected_instance
492
+ new_info = info
493
+ self .highlight_xlet (old_info , False )
494
+ self .highlight_xlet (new_info , True )
465
495
self .selected_instance = info
466
496
497
+ def highlight_xlet (self , info , highlighted ):
498
+ try :
499
+ proxy .highlightXlet ('(ssb)' , self .uuid , info ["id" ], highlighted )
500
+ except :
501
+ return
502
+
467
503
def previous_instance (self , * args ):
468
- self .instance_stack .set_transition_type (Gtk .StackTransitionType .OVER_RIGHT )
469
- index = self .instance_info .index (self .selected_instance )
470
- self .set_instance (self .instance_info [index - 1 ])
504
+ self .get_next_instance (False )
471
505
472
506
def next_instance (self , * args ):
473
- self .instance_stack .set_transition_type (Gtk .StackTransitionType .OVER_LEFT )
474
- index = self .instance_info .index (self .selected_instance )
475
- if index == len (self .instance_info ) - 1 :
476
- index = 0
477
- else :
478
- index += 1
479
- self .set_instance (self .instance_info [index ])
507
+ self .get_next_instance ()
508
+
509
+ def get_next_instance (self , positive_direction = True ):
510
+ transition = Gtk .StackTransitionType .OVER_LEFT if positive_direction else Gtk .StackTransitionType .OVER_RIGHT
511
+ self .instance_stack .set_transition_type (transition )
512
+ step = 1 if positive_direction else - 1
513
+ instances_length = len (self .instance_info )
514
+ start = self .instance_info .index (self .selected_instance )
515
+ nextIndex = (start + step ) % instances_length
516
+ self .set_instance (self .instance_info [nextIndex ])
517
+
518
+ def on_enabled_xlets_changed (self , key , * args ):
519
+ """
520
+ Args:
521
+ key ("enabled-applets"|"enabled-desklets")
522
+ """
523
+ current_ids = {info ["id" ] for info in self .instance_info }
524
+ new_ids = set ()
525
+ for definition in self .gsettings .get_strv (key ):
526
+ definition = definition .split (":" )
527
+ uuid , instance_id = (definition [- 2 ], definition [- 1 ]) if key == "enabled-applets" \
528
+ else (definition [0 ], definition [1 ])
529
+ if uuid != self .uuid : continue
530
+ new_ids .add (instance_id )
531
+ added_ids = new_ids - current_ids
532
+
533
+ removed_indices = []
534
+ selected_removed_index = - 1
535
+ for i , info in enumerate (self .instance_info ):
536
+ if info ["id" ] in new_ids : continue
537
+ removed_indices .append (i )
538
+ if info == self .selected_instance : selected_removed_index = i
539
+
540
+ if len (current_ids ) + len (added_ids ) == len (removed_indices ):
541
+ self .quit ()
542
+ return
543
+
544
+ for id in added_ids :
545
+ for dir in self .g_directories :
546
+ file = dir .get_child (id + ".json" )
547
+ if file .query_exists (None ):
548
+ self .create_new_settings_page (file .get_path ())
549
+ continue
550
+ # Config files have not been added yet, need to monitor directories
551
+ monitor = dir .monitor_directory (Gio .FileMonitorFlags .NONE , None )
552
+ monitor .connect ("changed" , self .on_config_file_added )
553
+ self .monitors .setdefault (id , []).append (monitor )
554
+
555
+ if (selected_removed_index != - 1 ):
556
+ self .get_next_instance ()
557
+
558
+ for index in sorted (removed_indices , reverse = True ):
559
+ self .monitors .get (self .instance_info [index ]["id" ], []).clear ()
560
+ self .instance_stack .remove (self .instance_stack .get_child_by_name (self .instance_info [index ]["id" ]))
561
+ self .instance_info .pop (index )
480
562
481
- # def unpack_args(self, args):
482
- # args = {}
563
+ if not self .has_multiple_instances (): self .hide_prev_next_buttons ()
564
+
565
+ def on_config_file_added (self , * args ):
566
+ file , event_type = args [1 ], args [- 1 ]
567
+ instance = file .get_basename ()[:- 5 ]
568
+ if event_type != Gio .FileMonitorEvent .CHANGES_DONE_HINT : return
569
+ if instance not in self .monitors : return
570
+ for monitor in self .monitors [instance ]: monitor .cancel ()
571
+ del self .monitors [instance ]
572
+ self .create_new_settings_page (file .get_path ())
573
+
574
+
575
+ def create_new_settings_page (self , path ):
576
+ self .create_settings_page (path )
577
+ self .window .show_all ()
578
+ if self .has_multiple_instances (): self .show_prev_next_buttons ()
579
+ self .highlight_xlet (self .selected_instance , True )
483
580
484
581
def backup (self , * args ):
485
582
dialog = Gtk .FileChooserDialog (_ ("Select or enter file to export to" ),
@@ -531,8 +628,7 @@ def reload_xlet(self, *args):
531
628
532
629
def quit (self , * args ):
533
630
if proxy :
534
- proxy .highlightXlet ('(ssb)' , self .uuid , self .selected_instance ["id" ], False )
535
-
631
+ self .highlight_xlet (self .selected_instance , False )
536
632
self .window .destroy ()
537
633
Gtk .main_quit ()
538
634
0 commit comments