1# -*- coding: utf-8 -*-
2
3# Copyright (C) 2011 Chris Dekter
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18import sys
19from gi.repository import Gtk
20
21from autokey import configmanager as cm, common
22from autokey.iomediator.key import Key
23
24from .dialogs import GlobalHotkeyDialog
25from .configwindow0 import get_ui
26
27
28ICON_NAME_MAP = {
29                _("Light"): common.ICON_FILE_NOTIFICATION,
30                _("Dark"): common.ICON_FILE_NOTIFICATION_DARK
31                }
32
33ICON_NAME_LIST = []
34
35class SettingsDialog:
36
37    KEY_MAP = GlobalHotkeyDialog.KEY_MAP
38    REVERSE_KEY_MAP = GlobalHotkeyDialog.REVERSE_KEY_MAP
39
40    def __init__(self, parent, configManager):
41        builder = get_ui("settingsdialog.xml")
42        self.ui = builder.get_object("settingsdialog")
43        builder.connect_signals(self)
44        self.ui.set_transient_for(parent)
45        self.configManager = configManager
46
47        # General Settings
48        self.autoStartCheckbox = builder.get_object("autoStartCheckbox")
49        self.autosaveCheckbox = builder.get_object("autosaveCheckbox")
50        self.showTrayCheckbox = builder.get_object("showTrayCheckbox")
51        self.disableCapslockCheckbox = builder.get_object("disableCapslockCheckbox")
52        self.allowKbNavCheckbox = builder.get_object("allowKbNavCheckbox")
53        self.allowKbNavCheckbox.hide()
54        self.sortByUsageCheckbox = builder.get_object("sortByUsageCheckbox")
55        # Added by Trey Blancher (ectospasm) 2015-09-16
56        self.triggerItemByInitial = builder.get_object("triggerItemByInitial")
57        self.enableUndoCheckbox = builder.get_object("enableUndoCheckbox")
58
59        self.iconStyleCombo = Gtk.ComboBoxText.new()
60        hbox = builder.get_object("hbox4")
61        hbox.pack_start(self.iconStyleCombo, False, True, 0)
62        hbox.show_all()
63
64        for key, value in list(ICON_NAME_MAP.items()):
65            self.iconStyleCombo.append_text(key)
66            ICON_NAME_LIST.append(value)
67        self.iconStyleCombo.set_sensitive(cm.ConfigManager.SETTINGS[cm.SHOW_TRAY_ICON])
68        self.iconStyleCombo.set_active(ICON_NAME_LIST.index(cm.ConfigManager.SETTINGS[cm.NOTIFICATION_ICON]))
69
70        self.autoStartCheckbox.set_active(cm.get_autostart().desktop_file_name is not None)
71        self.autosaveCheckbox.set_active(not cm.ConfigManager.SETTINGS[cm.PROMPT_TO_SAVE])
72        self.showTrayCheckbox.set_active(cm.ConfigManager.SETTINGS[cm.SHOW_TRAY_ICON])
73        self.disableCapslockCheckbox.set_active(cm.ConfigManager.is_modifier_disabled(Key.CAPSLOCK))
74        #self.allowKbNavCheckbox.set_active(cm.ConfigManager.SETTINGS[MENU_TAKES_FOCUS])
75        # Added by Trey Blancher (ectospasm) 2015-09-16
76        self.triggerItemByInitial.set_active(cm.ConfigManager.SETTINGS[cm.TRIGGER_BY_INITIAL])
77        self.sortByUsageCheckbox.set_active(cm.ConfigManager.SETTINGS[cm.SORT_BY_USAGE_COUNT])
78        self.enableUndoCheckbox.set_active(cm.ConfigManager.SETTINGS[cm.UNDO_USING_BACKSPACE])
79
80
81
82
83        # Hotkeys
84        self.showConfigDlg = GlobalHotkeyDialog(parent, configManager, self.on_config_response)
85        self.toggleMonitorDlg = GlobalHotkeyDialog(parent, configManager, self.on_monitor_response)
86        self.configKeyLabel = builder.get_object("configKeyLabel")
87        self.clearConfigButton = builder.get_object("clearConfigButton")
88        self.monitorKeyLabel = builder.get_object("monitorKeyLabel")
89        self.clearMonitorButton = builder.get_object("clearMonitorButton")
90
91        self.useConfigHotkey = self.__loadHotkey(configManager.configHotkey, self.configKeyLabel,
92                                                    self.showConfigDlg, self.clearConfigButton)
93        self.useServiceHotkey = self.__loadHotkey(configManager.toggleServiceHotkey, self.monitorKeyLabel,
94                                                    self.toggleMonitorDlg, self.clearMonitorButton)
95
96        # Script Engine Settings
97        self.userModuleChooserButton = builder.get_object("userModuleChooserButton")
98        if configManager.userCodeDir is not None:
99            self.userModuleChooserButton.set_current_folder(configManager.userCodeDir)
100            if configManager.userCodeDir in sys.path:
101                sys.path.remove(configManager.userCodeDir)
102
103    def on_save(self, widget, data=None):
104        if self.autoStartCheckbox.get_active():
105            cm.set_autostart_entry(cm.AutostartSettings("autokey-gtk.desktop", False))
106        else:
107            cm.delete_autostart_entry()
108
109        cm.ConfigManager.SETTINGS[cm.PROMPT_TO_SAVE] = not self.autosaveCheckbox.get_active()
110        cm.ConfigManager.SETTINGS[cm.SHOW_TRAY_ICON] = self.showTrayCheckbox.get_active()
111        #cm.ConfigManager.SETTINGS[MENU_TAKES_FOCUS] = self.allowKbNavCheckbox.get_active()
112        cm.ConfigManager.SETTINGS[cm.SORT_BY_USAGE_COUNT] = self.sortByUsageCheckbox.get_active()
113        # Added by Trey Blancher (ectospasm) 2015-09-16
114        cm.ConfigManager.SETTINGS[cm.TRIGGER_BY_INITIAL] = self.triggerItemByInitial.get_active()
115        cm.ConfigManager.SETTINGS[cm.UNDO_USING_BACKSPACE] = self.enableUndoCheckbox.get_active()
116        cm.ConfigManager.SETTINGS[cm.NOTIFICATION_ICON] = ICON_NAME_MAP[self.iconStyleCombo.get_active_text()]
117        self._save_disable_capslock_setting()
118        self.configManager.userCodeDir = self.userModuleChooserButton.get_current_folder()
119        sys.path.append(self.configManager.userCodeDir)
120
121        configHotkey = self.configManager.configHotkey
122        toggleHotkey = self.configManager.toggleServiceHotkey
123        app = self.configManager.app
124
125        if configHotkey.enabled:
126            app.hotkey_removed(configHotkey)
127        configHotkey.enabled = self.useConfigHotkey
128        if self.useConfigHotkey:
129            self.showConfigDlg.save(configHotkey)
130            app.hotkey_created(configHotkey)
131
132        if toggleHotkey.enabled:
133            app.hotkey_removed(toggleHotkey)
134        toggleHotkey.enabled = self.useServiceHotkey
135        if self.useServiceHotkey:
136            self.toggleMonitorDlg.save(toggleHotkey)
137            app.hotkey_created(toggleHotkey)
138
139        app.update_notifier_visibility()
140        self.configManager.config_altered(True)
141
142        self.hide()
143        self.destroy()
144
145    def _save_disable_capslock_setting(self):
146        # Only update the modifier key handling if the value changed.
147        if self.disableCapslockCheckbox.get_active() and not cm.ConfigManager.is_modifier_disabled(Key.CAPSLOCK):
148            cm.ConfigManager.disable_modifier(Key.CAPSLOCK)
149        elif not self.disableCapslockCheckbox.get_active() and cm.ConfigManager.is_modifier_disabled(Key.CAPSLOCK):
150            cm.ConfigManager.enable_modifier(Key.CAPSLOCK)
151
152    def on_cancel(self, widget, data=None):
153        self.hide()
154        self.destroy()
155
156    def __getattr__(self, attr):
157        # Magic fudge to allow us to pretend to be the ui class we encapsulate
158        return getattr(self.ui, attr)
159
160    def __loadHotkey(self, item, label, dialog, clearButton):
161        dialog.load(item)
162        if item.enabled:
163            key = item.hotKey.encode("utf-8")
164            label.set_text(item.get_hotkey_string())
165            clearButton.set_sensitive(True)
166            return True
167        else:
168            label.set_text(_("(None configured)"))
169            clearButton.set_sensitive(False)
170            return False
171
172    # ---- Signal handlers
173
174    def on_showTrayCheckbox_toggled(self, widget, data=None):
175        self.iconStyleCombo.set_sensitive(widget.get_active())
176
177    def on_setConfigButton_pressed(self, widget, data=None):
178        self.showConfigDlg.run()
179
180    def on_config_response(self, res):
181        if res == Gtk.ResponseType.OK:
182            self.useConfigHotkey = True
183            key = self.showConfigDlg.key
184            modifiers = self.showConfigDlg.build_modifiers()
185            self.configKeyLabel.set_text(self.build_hotkey_string(key, modifiers))
186            self.clearConfigButton.set_sensitive(True)
187
188    def on_clearConfigButton_pressed(self, widget, data=None):
189        self.useConfigHotkey = False
190        self.clearConfigButton.set_sensitive(False)
191        self.configKeyLabel.set_text(_("(None configured)"))
192        self.showConfigDlg.reset()
193
194    def on_setMonitorButton_pressed(self, widget, data=None):
195        self.toggleMonitorDlg.run()
196
197    def on_monitor_response(self, res):
198        if res == Gtk.ResponseType.OK:
199            self.useServiceHotkey = True
200            key = self.toggleMonitorDlg.key
201            modifiers = self.toggleMonitorDlg.build_modifiers()
202            self.monitorKeyLabel.set_text(self.build_hotkey_string(key, modifiers))
203            self.clearMonitorButton.set_sensitive(True)
204
205    def on_clearMonitorButton_pressed(self, widget, data=None):
206        self.useServiceHotkey = False
207        self.clearMonitorButton.set_sensitive(False)
208        self.monitorKeyLabel.set_text(_("(None configured)"))
209        self.toggleMonitorDlg.reset()
210
211