1#!/usr/bin/env python3 2# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- 3# LightDM GTK Greeter Settings 4# Copyright (C) 2014 Andrew P. <pan.pav.7c5@gmail.com> 5# 6# This program is free software: you can redistribute it and/or modify it 7# under the terms of the GNU General Public License version 3, as published 8# by the Free Software Foundation. 9# 10# This program is distributed in the hope that it will be useful, but 11# WITHOUT ANY WARRANTY; without even the implied warranties of 12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 13# PURPOSE. See the GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License along 16# with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 19from lightdm_gtk_greeter_settings.MultiheadSetupDialog import MultiheadSetupDialog 20from lightdm_gtk_greeter_settings import ( 21 helpers, 22 OptionEntry, 23 OptionGroup) 24from lightdm_gtk_greeter_settings.helpers import ( 25 WidgetsWrapper) 26 27 28__all__ = ['MonitorsGroup'] 29 30 31class MonitorsGroup(OptionGroup.BaseGroup): 32 33 GroupPrefix = 'monitor:' 34 EntriesSetup = (('name', OptionEntry.StringEntry), 35 ('background', OptionEntry.BackgroundEntry), 36 ('user-background', OptionEntry.BooleanEntry), 37 ('laptop', OptionEntry.BooleanEntry)) 38 39 def __init__(self, widgets): 40 super().__init__(widgets) 41 self._widgets = helpers.WidgetsWrapper(widgets) 42 self._groups = [] 43 self._adapters = {key: OptionGroup.OneToManyEntryAdapter() 44 for key, __ in self.EntriesSetup} 45 self._dialog = None 46 47 self._groups_wrapper = helpers.SimpleDictWrapper( 48 deleter=self._remove_group, 49 add=self._add_group, 50 itergetter=lambda: iter(self._groups)) 51 52 self._widgets['multihead_label'].connect('activate-link', self._on_label_link_activate) 53 54 def read(self, config): 55 for group in self._groups: 56 group.clear() 57 self._groups.clear() 58 59 for groupname in config: 60 if not groupname.startswith(MonitorsGroup.GroupPrefix): 61 continue 62 63 monitor = groupname[len(MonitorsGroup.GroupPrefix):].strip() 64 self._add_group(monitor, groupname, config) 65 66 def write(self, config, is_changed=None): 67 groups = set(group.entries['name'].value for group in self._groups) 68 groups_to_remove = tuple(name for name in config 69 if (name.startswith(self.GroupPrefix) and 70 name[len(self.GroupPrefix):].strip() not in groups)) 71 72 for group in self._groups: 73 name = group.entries['name'] 74 new_name = self.GroupPrefix + ' ' + name.value 75 76 if group.name == new_name: 77 def changed_(entry): 78 if entry == name: 79 return False 80 return not is_changed or is_changed(entry) 81 else: 82 def changed_(entry): 83 return entry != name 84 85 group.name = new_name 86 group.write(config, is_changed=changed_) 87 88 for name in groups_to_remove: 89 config_group = config[name] 90 for key, *__ in self.EntriesSetup: 91 del config_group[key] 92 93 def clear(self): 94 if not self._groups and not self._adapters: 95 return 96 for group in self._groups: 97 group.clear() 98 self._groups.clear() 99 100 def activate(self, key, entry): 101 self._adapters[key].activate(entry) 102 103 @property 104 def groups(self): 105 return self._groups_wrapper 106 107 def _add_group(self, monitor='', groupname='', config=None): 108 group = OptionGroup.SimpleGroup(groupname, self._widgets) 109 110 group.entry_added.connect(lambda g, s, e, k: self.entry_added.emit(s, e, k)) 111 group.entry_removed.connect(lambda g, s, e, k: self.entry_removed.emit(s, e, k)) 112 113 group.options = {key: (adapter.new_entry, None) 114 for key, adapter in self._adapters.items()} 115 116 if config: 117 group.read(config) 118 119 name = group.entries['name'] 120 name.enabled = True 121 name.value = monitor 122 123 self._groups.append(group) 124 return group 125 126 def _remove_group(self, group): 127 group.clear() 128 self._groups.remove(group) 129 130 def _on_label_link_activate(self, label, uri): 131 if not self._dialog: 132 self._dialog = MultiheadSetupDialog(self) 133 self._dialog.props.transient_for = self._widgets['multihead_label'].get_toplevel() 134 135 for key, klass in self.EntriesSetup: 136 self._adapters[key].base_entry = klass(WidgetsWrapper(self._dialog.builder, key)) 137 138 self._dialog.run() 139 self._dialog.hide() 140 return True 141