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