class TypingTweakGroup(Gtk.Box, TweakGroup):

    XKB_GSETTINGS_SCHEMA = "org.gnome.desktop.input-sources"
    XKB_GSETTINGS_NAME = "xkb-options"
    # These are configurable in gnome-control-center. grp_led is unsupported
    XKB_OPTIONS_BLACKLIST = {"lv3","Compose key","grp","grp_led"}

    def __init__(self):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=3)
        self._option_objects = []
        ok = False
        try:
            self._kbdsettings = GSettingsSetting(self.XKB_GSETTINGS_SCHEMA)
            self._kbdsettings.connect("changed::"+self.XKB_GSETTINGS_NAME, self._on_changed)
            self._xkb_info = GnomeDesktop.XkbInfo()
            ok = True
            self.loaded = True
        except GSettingsMissingError:
            logging.info("Typing missing schema %s" % self.XKB_GSETTINGS_SCHEMA)
            self.loaded = False            
        except AttributeError:
            logging.warning("Typing missing GnomeDesktop.gir with Xkb support")
            self.loaded = False
        finally:
            if ok:
                for opt in set(self._xkb_info.get_all_option_groups()) - self.XKB_OPTIONS_BLACKLIST:
                    obj = _XkbOption(opt, self._kbdsettings, self._xkb_info)
                    self._option_objects.append(obj)
                    self.pack_start(obj, False, False, 0)
        TweakGroup.__init__(self, _("Typing"), *self._option_objects)

    def _on_changed(self, *args):
        for obj in self._option_objects:
            obj.reload()
예제 #2
0
class _GSettingsTweak(Tweak):
    def __init__(self, schema_name, key_name, **options):
        self.schema_name = schema_name
        self.key_name = key_name
        self.settings = GSettingsSetting(schema_name, **options)
        Tweak.__init__(self,
            self.settings.schema_get_summary(key_name),
            self.settings.schema_get_description(key_name),
            **options)
예제 #3
0
 def __init__(self):
     Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=3)
     self._option_objects = []
     self._sg = Gtk.SizeGroup(mode=Gtk.SizeGroupMode.HORIZONTAL)
     ok = False
     try:
         self._kbdsettings = GSettingsSetting(self.XKB_GSETTINGS_SCHEMA)
         self._kbdsettings.connect("changed::"+self.XKB_GSETTINGS_NAME, self._on_changed)
         self._xkb_info = GnomeDesktop.XkbInfo()
         ok = True
         self.loaded = True
     except GSettingsMissingError:
         logging.info("Typing missing schema %s" % self.XKB_GSETTINGS_SCHEMA)
         self.loaded = False            
     except AttributeError:
         logging.warning("Typing missing GnomeDesktop.gir with Xkb support")
         self.loaded = False
     finally:
         if ok:
             for opt in set(self._xkb_info.get_all_option_groups()) - self.XKB_OPTIONS_BLACKLIST:
                 obj = _XkbOption(opt, self._kbdsettings, self._xkb_info)
                 self._sg.add_widget(obj._combo)
                 self._option_objects.append(obj)
                 self.pack_start(obj, False, False, 0)
     TweakGroup.__init__(self, _("Typing"), *self._option_objects)
예제 #4
0
    def __init__(self, **options):
        Tweak.__init__(self, "Shell theme", "Install custom or user themes for gnome-shell", **options)

        #check the shell is running and the usertheme extension is present
        error = "Unknown"
        try:
            self._shell = GnomeShell()
        except:
            error = "Shell not running"
        try:
            extensions = self._shell.list_extensions()
            if ThemeInstaller.THEME_EXT_NAME in extensions and extensions[ThemeInstaller.THEME_EXT_NAME]["state"] == 1:
                #check the correct gsettings key is present
                try:
                    self._settings = GSettingsSetting(ThemeInstaller.THEME_GSETTINGS_SCHEMA)
                    name = self._settings.get_value(ThemeInstaller.THEME_GSETTINGS_NAME)
                    print "!!!!", name
                    error = None
                except:
                    error = "User Theme extension schema missing"

            else:
                error = "User Theme extension not enabled"
        except Exception, e:
            error = "Could not list shell extensions"
예제 #5
0
    def __init__(self, **options):
        Tweak.__init__(self, "Shell theme", "Install custom or user themes for gnome-shell", **options)

        #check the shell is running and the usertheme extension is present
        error = _("Unknown error")
        try:
            self._shell = GnomeShellFactory().get_shell()
        except:
            logging.warning("Shell not running", exc_info=True)
            error = _("Shell not running")
        try:
            extensions = self._shell.list_extensions()
            if ShellThemeTweak.THEME_EXT_NAME in extensions and extensions[ShellThemeTweak.THEME_EXT_NAME]["state"] == 1:
                #check the correct gsettings key is present
                try:
                    self._settings = GSettingsSetting(ShellThemeTweak.THEME_GSETTINGS_SCHEMA)
                    name = self._settings.get_string(ShellThemeTweak.THEME_GSETTINGS_NAME)

                    ext = extensions[ShellThemeTweak.THEME_EXT_NAME]
                    logging.debug("Shell user-theme extension\n%s" % pprint.pformat(ext))

                    error = None
                except:
                    logging.warning(
                        "Could not find user-theme extension in %s" % ','.join(extensions.keys()),
                        exc_info=True)
                    error = _("Shell user-theme extension incorrectly installed")

            else:
                error = _("Shell user-theme extension not enabled")
        except Exception, e:
            logging.warning("Could not list shell extensions", exc_info=True)
            error = _("Could not list shell extensions")
예제 #6
0
 def __init__(self, schema_name, key_name, **options):
     self.schema_name = schema_name
     self.key_name = key_name
     self.settings = GSettingsSetting(schema_name, **options)
     Tweak.__init__(self,
         options.get("summary",self.settings.schema_get_summary(key_name)),
         options.get("description",self.settings.schema_get_description(key_name)),
         **options)
    def __init__(self, **options):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
        Tweak.__init__(self, _("Shell theme"), _("Install custom or user themes for gnome-shell"), **options)

        #check the shell is running and the usertheme extension is present
        error = _("Unknown error")
        self._shell = _shell

        if self._shell is None:
            logging.warning("Shell not running", exc_info=True)
            error = _("Shell not running")
        else:
            try:
                extensions = self._shell.list_extensions()
                if ShellThemeTweak.THEME_EXT_NAME in extensions and extensions[ShellThemeTweak.THEME_EXT_NAME]["state"] == 1:
                    #check the correct gsettings key is present
                    try:
                        if os.path.exists(ShellThemeTweak.THEME_GSETTINGS_DIR):
                            self._settings = GSettingsSetting(ShellThemeTweak.THEME_GSETTINGS_SCHEMA,
                                                              schema_dir=ShellThemeTweak.THEME_GSETTINGS_DIR)
                        else:
                            self._settings = GSettingsSetting(ShellThemeTweak.THEME_GSETTINGS_SCHEMA)
                        name = self._settings.get_string(ShellThemeTweak.THEME_GSETTINGS_NAME)

                        ext = extensions[ShellThemeTweak.THEME_EXT_NAME]
                        logging.debug("Shell user-theme extension\n%s" % pprint.pformat(ext))

                        error = None
                    except:
                        logging.warning(
                            "Could not find user-theme extension in %s" % ','.join(extensions.keys()),
                            exc_info=True)
                        error = _("Shell user-theme extension incorrectly installed")

                else:
                    error = _("Shell user-theme extension not enabled")
            except Exception, e:
                logging.warning("Could not list shell extensions", exc_info=True)
                error = _("Could not list shell extensions")
예제 #8
0
class ThemeInstaller(Tweak):

    THEME_EXT_NAME = "*****@*****.**"
    THEME_GSETTINGS_SCHEMA = "org.gnome.shell.extensions.user-theme"
    THEME_GSETTINGS_NAME = "name"
    THEME_DIR = os.path.join(GLib.get_home_dir(), ".themes")

    def __init__(self, **options):
        Tweak.__init__(self, "Shell theme", "Install custom or user themes for gnome-shell", **options)

        #check the shell is running and the usertheme extension is present
        error = "Unknown"
        try:
            self._shell = GnomeShell()
        except:
            error = "Shell not running"
        try:
            extensions = self._shell.list_extensions()
            if ThemeInstaller.THEME_EXT_NAME in extensions and extensions[ThemeInstaller.THEME_EXT_NAME]["state"] == 1:
                #check the correct gsettings key is present
                try:
                    self._settings = GSettingsSetting(ThemeInstaller.THEME_GSETTINGS_SCHEMA)
                    name = self._settings.get_value(ThemeInstaller.THEME_GSETTINGS_NAME)
                    print "!!!!", name
                    error = None
                except:
                    error = "User Theme extension schema missing"

            else:
                error = "User Theme extension not enabled"
        except Exception, e:
            error = "Could not list shell extensions"

        if error:
            info = Gtk.InfoBar()
            info.props.message_type = Gtk.MessageType.INFO
            info.get_content_area().add(Gtk.Label(error))
            self.widget = build_label_beside_widget(self.name, info)
            self.widget_for_size_group = info
        else:
            hb = Gtk.HBox()
            b = Gtk.Button.new_from_stock(Gtk.STOCK_REVERT_TO_SAVED)
            b.connect("clicked", self._on_revert)
            hb.pack_start(b, False, False, 5)

            chooser = _ThemeZipChooser()
            chooser.connect("file-set", self._on_file_set)
            hb.pack_start(chooser, False, False, 0)

            self.widget = build_label_beside_widget(self.name, hb)
            self.widget_for_size_group = chooser
예제 #9
0
def adjust_schema_for_overrides(originalSchema, key, options):
    if (_shell is None):
        return originalSchema

    if (_shell.mode == 'classic'):
        overridesSchema = "org.gnome.shell.extensions.classic-overrides"
        overridesFile = None
    else:
        overridesSchema = "org.gnome.shell.overrides"
        overridesFile = "org.gnome.shell.gschema.xml"

    try:
        if (key in GSettingsSetting(
                overridesSchema, schema_filename=overridesFile).list_keys()):
            options['schema_filename'] = overridesFile
            return overridesSchema
    except GSettingsMissingError, e:
        logging.info("GSetting missing %s" % (e.message))
예제 #10
0
 def __init__(self, name, schema_name, key_name, **options):
     schema_name = adjust_schema_for_overrides(schema_name, key_name,
                                               options)
     self.schema_name = schema_name
     self.key_name = key_name
     self._extra_info = None
     if 'uid' not in options:
         options['uid'] = key_name
     try:
         self.settings = GSettingsSetting(schema_name, **options)
         Tweak.__init__(
             self, name,
             options.get("description",
                         self.settings.schema_get_description(key_name)),
             **options)
     except GSettingsMissingError, e:
         self.settings = GSettingsFakeSetting()
         Tweak.__init__(self, "", "")
         self.loaded = False
         logging.info("GSetting missing %s" % (e.message))
예제 #11
0
    def __init__(self):
        try:
            proxy = _ShellProxy()
            settings = GSettingsSetting("org.gnome.shell")
            v = map(int, proxy.version.split("."))

            if v >= [3, 5, 0]:
                self.shell = GnomeShell36(proxy, settings)
            elif v >= [3, 3, 2]:
                self.shell = GnomeShell34(proxy, settings)
            elif v >= [3, 1, 4]:
                self.shell = GnomeShell32(proxy, settings)
            else:
                logging.warn("Shell version not supported")
                self.shell = None

            logging.debug("Shell version: %s", str(v))
        except:
            self.shell = None
            logging.warn("Shell not installed or running")
예제 #12
0
    def __init__(self, **options):
        Tweak.__init__(self, "Dynamic workspaces", "Disable gnome-shell dynamic workspace management, use static workspaces", **options)

        settings = GSettingsSetting(self.NUM_WORKSPACES_SCHEMA, **options)
        adj = Gtk.Adjustment(1, 1, 99, 1)
        sb = Gtk.SpinButton(adjustment=adj, digits=0)
        settings.bind(self.NUM_WORKSPACES_KEY, adj, "value", Gio.SettingsBindFlags.DEFAULT)

        settings = GSettingsSetting(self.DYNAMIC_SCHEMA, **options)
        sw = Gtk.Switch()
        settings.bind(self.DYNAMIC_KEY, sw, "active", Gio.SettingsBindFlags.DEFAULT)

        #sw.bind_property ("active", sb, "sensitive", GObject.BindingFlags.SYNC_CREATE)
        sb.set_sensitive(not settings[self.DYNAMIC_KEY])
        sw.connect('notify::active', lambda _sw,_param,_sb: _sb.set_sensitive(not _sw.get_active()), sb)

        hb = Gtk.HBox(spacing = 4)
        hb.pack_start(sw, False, False, 0)
        hb.pack_start(sb, True, True, 0)

        self.widget = build_label_beside_widget(self.name, hb)
        self.widget_for_size_group = hb
class ShellThemeTweak(Gtk.Box, Tweak):

    THEME_EXT_NAME = "*****@*****.**"
    THEME_GSETTINGS_SCHEMA = "org.gnome.shell.extensions.user-theme"
    THEME_GSETTINGS_NAME = "name"
    THEME_GSETTINGS_DIR = os.path.join(GLib.get_user_data_dir(), "gnome-shell", "extensions",
                                       THEME_EXT_NAME, "schemas")
    LEGACY_THEME_DIR = os.path.join(GLib.get_home_dir(), ".themes")
    THEME_DIR = os.path.join(GLib.get_user_data_dir(), "themes")

    def __init__(self, **options):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
        Tweak.__init__(self, _("Shell theme"), _("Install custom or user themes for gnome-shell"), **options)

        #check the shell is running and the usertheme extension is present
        error = _("Unknown error")
        self._shell = _shell

        if self._shell is None:
            logging.warning("Shell not running", exc_info=True)
            error = _("Shell not running")
        else:
            try:
                extensions = self._shell.list_extensions()
                if ShellThemeTweak.THEME_EXT_NAME in extensions and extensions[ShellThemeTweak.THEME_EXT_NAME]["state"] == 1:
                    #check the correct gsettings key is present
                    try:
                        if os.path.exists(ShellThemeTweak.THEME_GSETTINGS_DIR):
                            self._settings = GSettingsSetting(ShellThemeTweak.THEME_GSETTINGS_SCHEMA,
                                                              schema_dir=ShellThemeTweak.THEME_GSETTINGS_DIR)
                        else:
                            self._settings = GSettingsSetting(ShellThemeTweak.THEME_GSETTINGS_SCHEMA)
                        name = self._settings.get_string(ShellThemeTweak.THEME_GSETTINGS_NAME)

                        ext = extensions[ShellThemeTweak.THEME_EXT_NAME]
                        logging.debug("Shell user-theme extension\n%s" % pprint.pformat(ext))

                        error = None
                    except:
                        logging.warning(
                            "Could not find user-theme extension in %s" % ','.join(extensions.keys()),
                            exc_info=True)
                        error = _("Shell user-theme extension incorrectly installed")

                else:
                    error = _("Shell user-theme extension not enabled")
            except Exception, e:
                logging.warning("Could not list shell extensions", exc_info=True)
                error = _("Could not list shell extensions")

        if error:
            cb = build_combo_box_text(None)
            build_label_beside_widget(self.name, cb,
                        warning=error,
                        hbox=self)
            self.widget_for_size_group = cb
        else:
            #include both system, and user themes
            #note: the default theme lives in /system/data/dir/gnome-shell/theme
            #      and not themes/, so add it manually later
            dirs = [os.path.join(d, "themes") for d in GLib.get_system_data_dirs()]
            dirs += [ShellThemeTweak.THEME_DIR]
            dirs += [ShellThemeTweak.LEGACY_THEME_DIR]

            valid = walk_directories(dirs, lambda d:
                        os.path.exists(os.path.join(d, "gnome-shell")) and \
                        os.path.exists(os.path.join(d, "gnome-shell", "gnome-shell.css")))
            #the default value to reset the shell is an empty string
            valid.extend( ("",) )

            #build a combo box with all the valid theme options
            #manually add Adwaita to represent the default
            cb = build_combo_box_text(
                    self._settings.get_string(ShellThemeTweak.THEME_GSETTINGS_NAME),
                    *make_combo_list_with_default(
                        valid,
                        "",
                        default_text=_("<i>Default</i>")))
            cb.connect('changed', self._on_combo_changed)
            self._combo = cb

            #a filechooser to install new themes
            chooser = FileChooserButton(
                        _("Select a theme"),
                        True,
                        ["application/zip"])
            chooser.connect("file-set", self._on_file_set)

            build_label_beside_widget(self.name, chooser, cb, hbox=self)
            self.widget_for_size_group = cb
예제 #14
0
class ShellThemeTweak(Gtk.Box, Tweak):

    THEME_EXT_NAME = "*****@*****.**"
    THEME_GSETTINGS_SCHEMA = "org.gnome.shell.extensions.user-theme"
    THEME_GSETTINGS_NAME = "name"
    THEME_GSETTINGS_DIR = os.path.join(GLib.get_user_data_dir(), "gnome-shell",
                                       "extensions", THEME_EXT_NAME, "schemas")
    LEGACY_THEME_DIR = os.path.join(GLib.get_home_dir(), ".themes")
    THEME_DIR = os.path.join(GLib.get_user_data_dir(), "themes")

    def __init__(self, **options):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
        Tweak.__init__(self, _("Shell"),
                       _("Install custom or user themes for gnome-shell"),
                       **options)

        #check the shell is running and the usertheme extension is present
        error = _("Unknown error")
        self._shell = _shell

        if self._shell is None:
            logging.warning("Shell not running", exc_info=True)
            error = _("Shell not running")
        else:
            try:
                extensions = self._shell.list_extensions()
                if ShellThemeTweak.THEME_EXT_NAME in extensions and extensions[
                        ShellThemeTweak.THEME_EXT_NAME]["state"] == 1:
                    #check the correct gsettings key is present
                    try:
                        if os.path.exists(ShellThemeTweak.THEME_GSETTINGS_DIR):
                            self._settings = GSettingsSetting(
                                ShellThemeTweak.THEME_GSETTINGS_SCHEMA,
                                schema_dir=ShellThemeTweak.THEME_GSETTINGS_DIR)
                        else:
                            self._settings = GSettingsSetting(
                                ShellThemeTweak.THEME_GSETTINGS_SCHEMA)
                        name = self._settings.get_string(
                            ShellThemeTweak.THEME_GSETTINGS_NAME)

                        ext = extensions[ShellThemeTweak.THEME_EXT_NAME]
                        logging.debug("Shell user-theme extension\n%s" %
                                      pprint.pformat(ext))

                        error = None
                    except:
                        logging.warning(
                            "Could not find user-theme extension in %s" %
                            ','.join(list(extensions.keys())),
                            exc_info=True)
                        error = _(
                            "Shell user-theme extension incorrectly installed")

                else:
                    error = _("Shell user-theme extension not enabled")
            except Exception as e:
                logging.warning("Could not list shell extensions",
                                exc_info=True)
                error = _("Could not list shell extensions")

        if error:
            cb = build_combo_box_text(None)
            build_label_beside_widget(self.name, cb, warning=error, hbox=self)
            self.widget_for_size_group = cb
        else:
            #include both system, and user themes
            #note: the default theme lives in /system/data/dir/gnome-shell/theme
            #      and not themes/, so add it manually later
            dirs = [
                os.path.join(d, "themes") for d in GLib.get_system_data_dirs()
            ]
            dirs += [ShellThemeTweak.THEME_DIR]
            dirs += [ShellThemeTweak.LEGACY_THEME_DIR]

            valid = walk_directories(dirs, lambda d:
                        os.path.exists(os.path.join(d, "gnome-shell")) and \
                        os.path.exists(os.path.join(d, "gnome-shell", "gnome-shell.css")))
            #the default value to reset the shell is an empty string
            valid.extend(("", ))
            valid = set(valid)

            #build a combo box with all the valid theme options
            #manually add Adwaita to represent the default
            cb = build_combo_box_text(
                self._settings.get_string(
                    ShellThemeTweak.THEME_GSETTINGS_NAME),
                *make_combo_list_with_default(
                    valid, "", default_text=_("<i>Default</i>")))
            cb.connect('changed', self._on_combo_changed)
            self._combo = cb

            #a filechooser to install new themes
            chooser = FileChooserButton(_("Select a theme"), True,
                                        ["application/zip"])
            chooser.connect("file-set", self._on_file_set)

            build_label_beside_widget(self.name, chooser, cb, hbox=self)
            self.widget_for_size_group = cb

    def _on_file_set(self, chooser):
        f = chooser.get_filename()

        with zipfile.ZipFile(f, 'r') as z:
            try:
                fragment = ()
                theme_name = None
                for n in z.namelist():
                    if n.endswith("gnome-shell.css"):
                        fragment = n.split("/")[0:-1]
                    if n.endswith("gnome-shell/theme.json"):
                        logging.info("New style theme detected (theme.json)")
                        #new style theme - extract the name from the json file
                        tmp = tempfile.mkdtemp()
                        z.extract(n, tmp)
                        with open(os.path.join(tmp, n)) as f:
                            try:
                                theme_name = json.load(
                                    f)["shell-theme"]["name"]
                            except:
                                logging.warning("Invalid theme format",
                                                exc_info=True)

                if not fragment:
                    raise Exception("Could not find gnome-shell.css")

                if not theme_name:
                    logging.info(
                        "Old style theme detected (missing theme.json)")
                    #old style themes name was taken from the zip name
                    if fragment[0] == "theme" and len(fragment) == 1:
                        theme_name = os.path.basename(f)
                    else:
                        theme_name = fragment[0]

                theme_members_path = "/".join(fragment)

                ok, updated = extract_zip_file(
                    z, theme_members_path,
                    os.path.join(ShellThemeTweak.THEME_DIR, theme_name,
                                 "gnome-shell"))

                if ok:
                    if updated:
                        self.notify_information(
                            _("%s theme updated successfully") % theme_name)
                    else:
                        self.notify_information(
                            _("%s theme installed successfully") % theme_name)

                    #I suppose I could rely on updated as indicating whether to add the theme
                    #name to the combo, but just check to see if it is already there
                    model = self._combo.get_model()
                    if theme_name not in [r[0] for r in model]:
                        model.append((theme_name, theme_name))
                else:
                    self.notify_information(_("Error installing theme"))

            except:
                #does not look like a valid theme
                self.notify_information(_("Invalid theme"))
                logging.warning("Error parsing theme zip", exc_info=True)

        #set button back to default state
        chooser.unselect_all()

    def _on_combo_changed(self, combo):
        val = combo.get_model().get_value(combo.get_active_iter(), 0)
        self._settings.set_string(ShellThemeTweak.THEME_GSETTINGS_NAME, val)
예제 #15
0
def set_theme(desk_env, t_type, theme):
    if desk_env not in SUPPORTED_DESKENVS:
        raise Exception('Invalid desktop environment!')

    elif not theme:
        logger.error('{}\'s {} theme not set '.format(correct_name_case(desk_env), correct_name_case(t_type)))
        return

    if t_type in ['gtk', 'icons']:
        from gi.repository import Gio
        if desk_env == 'cinnamon':
            gsettings_string = 'org.cinnamon.desktop.interface'
        else:
            gsettings_string = 'org.gnome.desktop.interface'

        gsettings = Gio.Settings.new(gsettings_string)

    # Safety fallback, shouldn't happen
    else:
        gsettings = None

    if t_type == 'gtk':

        # Easy peasy
        # For GNOME and Cinnamon
        gsettings['gtk-theme'] = theme

        # For XFCE
        if desk_env == 'xfce':
            from subprocess import run, CalledProcessError
            try:
                # noinspection SpellCheckingInspection
                run(['xfconf-query', '-c', 'xsettings', '-p', '/Net/ThemeName', '-s', theme])
            except CalledProcessError:
                logger.error('Could not apply GTK theme')
                return

        # Switching GTK themes in KDE is a little bit more complicated than the others...
        # For KDE
        elif desk_env == 'kde':
            from subprocess import run
            import configparser
            import fileinput
            import sys
            from automathemely.autoth_tools.utils import get_bin

            # Set GTK3 theme
            # This would usually be done with kwriteconfig but since there is no way to notify GTK3 apps that the
            # theme has changed in KDE like with GTK2 anyway we might as well do it this way
            parser = configparser.ConfigParser(strict=False)
            # Prevent changing the key's case
            parser.optionxform = lambda option: option
            parser.read(PATH_CONSTANTS['kde-gtk-config']['gtk3'])

            parser['Settings']['gtk-theme-name'] = theme
            with open(PATH_CONSTANTS['kde-gtk-config']['gtk3'], 'w') as f:
                parser.write(f, space_around_delimiters=False)

            # Search for gtk2 config file in theme dir in PATH_CONSTANTS dirs
            # As if it wasn't messy enough already...
            match = walk_filter_dirs(PATH_CONSTANTS['general-themes'], lambda parent_dir, t: Path(parent_dir)
                                     .joinpath(t).glob('gtk-2.*/gtkrc') and t.lower() != 'default', return_parent=True)

            if not match:
                logger.warning('The selected GTK theme does not contain a GTK2 theme, so some applications may '
                               'look odd')
            else:
                # If there are several themes with the same name in different directories, only get the first one
                # to match according to the dirs hierarchy in PATH_CONSTANTS
                theme_parent = match[0][1]

                if not Path(PATH_CONSTANTS['kde-gtk-config']['gtk2']).is_file():
                    logger.warning('GTK2 config file not found, set a theme from System Settings at least once and '
                                   'try again')

                # Write GTK2 config
                else:
                    line_replaced, previous_is_autogen_comment = False, False
                    for line in fileinput.input(PATH_CONSTANTS['kde-gtk-config']['gtk2'], inplace=True):

                        if line.startswith('# Configs for GTK2 programs'):
                            previous_is_autogen_comment = True
                            sys.stdout.write(line)

                        # Even in kde-config-gtk they don't seem to agree if this may not actually be needed, but
                        # just in case here it is
                        elif line.startswith('include'):
                            print('include "{}"'.format(str(Path(theme_parent).joinpath(theme, 'gtk-2.0', 'gtkrc'))))

                        # This is the one that matters
                        elif line.startswith('gtk-theme-name='):
                            print('gtk-theme-name="{}"'.format(theme))
                            line_replaced = True

                        else:
                            if previous_is_autogen_comment and not line.startswith('# Edited by AutomaThemely'):
                                print('# Edited by AutomaThemely')
                                previous_is_autogen_comment = False
                            sys.stdout.write(line)

                    if not line_replaced:
                        logger.warning('GTK2 config file is invalid, set a theme from System Settings at least '
                                       'once and try again')
                    else:
                        # Send signal to GTK2 apps to refresh their themes
                        run([get_bin('kde-refresh-gtk2')])

    elif t_type == 'icons':

        # For GNOME and Cinnamon
        gsettings['icon-theme'] = theme

        # For XFCE
        if desk_env == 'xfce':
            from subprocess import run, CalledProcessError
            try:
                # noinspection SpellCheckingInspection
                run(['xfconf-query', '-c', 'xsettings', '-p', '/Net/IconThemeName', '-s', theme])
            except CalledProcessError:
                logger.error('Could not apply icons theme')
                return

    elif t_type == 'shell':
        # This is WAY out of my level, I'll just let the professionals handle this one...
        try:
            import gtweak
        except ImportError:
            logger.error('GNOME Tweaks not installed')
            return

        from gtweak.gshellwrapper import GnomeShellFactory
        from gtweak.defs import GSETTINGS_SCHEMA_DIR, LOCALE_DIR
        # This could probably be implemented in house but since we're already importing from gtweak I guess it'll stay
        # this way for now
        from gtweak.gsettings import GSettingsSetting

        gtweak.GSETTINGS_SCHEMA_DIR = GSETTINGS_SCHEMA_DIR
        gtweak.LOCALE_DIR = LOCALE_DIR
        shell = GnomeShellFactory().get_shell()
        shell_theme_name = '*****@*****.**'
        shell_theme_schema = 'org.gnome.shell.extensions.user-theme'
        shell_theme_schema_dir = Path(PATH_CONSTANTS['shell-user-extensions']).joinpath(shell_theme_name, 'schemas')

        if not shell:
            logger.error('GNOME Shell not running')
            return
        else:
            # noinspection PyBroadException
            try:
                shell_extensions = shell.list_extensions()
            except Exception:
                logger.error('GNOME Shell extensions could not be loaded')
                return
            else:
                # noinspection PyBroadException
                try:
                    if shell_theme_name in shell_extensions and shell_extensions[shell_theme_name]['state'] == 1:
                        # If shell user-theme was installed locally e. g. through extensions.gnome.org
                        if Path(shell_theme_schema_dir).is_dir():
                            user_shell_settings = GSettingsSetting(shell_theme_schema,
                                                                   schema_dir=str(shell_theme_schema_dir))
                        # If it was installed as a system extension
                        else:
                            user_shell_settings = GSettingsSetting(shell_theme_schema)
                    else:
                        logger.error('GNOME Shell user theme extension not enabled')
                        return
                except Exception:
                    logger.error('Could not load GNOME Shell user theme extension')
                    return
                else:
                    # To set the default theme you have to input an empty string, but since that won't work with the
                    # Setting Manager's ComboBoxes we set it by this placeholder name
                    if theme == 'default':
                        theme = ''

                    # Set the GNOME Shell theme
                    user_shell_settings.set_string('name', theme)

    elif t_type == 'lookandfeel':
        from subprocess import run, CalledProcessError
        try:
            # noinspection SpellCheckingInspection
            run(['lookandfeeltool', '-a', '{}'.format(theme)], check=True)
        except CalledProcessError:
            logger.error('Could not apply Look and Feel theme')
            return

    elif t_type == 'desktop':
        from gi.repository import Gio
        cinnamon_settings = Gio.Settings.new('org.cinnamon.theme')
        cinnamon_settings['name'] = theme
예제 #16
0
    def __init__(self, **options):
        Gtk.Box.__init__(self)
        Tweak.__init__(self, _("Hinting"), _("Antialiasing"))

        try:
            self.settings = GSettingsSetting("org.gnome.desktop.interface")
        except:
            self.settings = None
            logging.warn(
                "org.gnome.desktop.interface not installed or running")

        if not self.settings:
            return

        self.set_spacing(12)
        self.props.margin_top = 12

        label = Gtk.Label(_("Hinting"))
        label.props.yalign = 0.0
        label.padding = 10
        self.pack_start(label, False, False, 0)

        hint_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.pack_start(hint_box, True, True, 0)

        self.btn_full = Gtk.RadioButton.new_from_widget(None)
        self.btn_full.set_label(_("Full"))
        self.btn_full.set_active(self.settings["font-hinting"] == "full")
        self.btn_full.connect("toggled", self.on_hint_button_toggled)
        hint_box.pack_start(self.btn_full, False, False, 0)

        self.btn_med = Gtk.RadioButton.new_from_widget(self.btn_full)
        self.btn_med.set_label(_("Medium"))
        self.btn_med.set_active(self.settings["font-hinting"] == "medium")
        self.btn_med.connect("toggled", self.on_hint_button_toggled)
        hint_box.pack_start(self.btn_med, False, False, 0)

        self.btn_slight = Gtk.RadioButton.new_from_widget(self.btn_full)
        self.btn_slight.set_label(_("Slight"))
        self.btn_slight.set_active(self.settings["font-hinting"] == "slight")
        self.btn_slight.connect("toggled", self.on_hint_button_toggled)
        hint_box.pack_start(self.btn_slight, False, False, 0)

        self.btn_hnone = Gtk.RadioButton.new_from_widget(self.btn_full)
        self.btn_hnone.set_label(_("None"))
        self.btn_hnone.set_active(self.settings["font-hinting"] == "none")
        self.btn_hnone.connect("toggled", self.on_hint_button_toggled)
        hint_box.pack_start(self.btn_hnone, False, False, 0)

        label = Gtk.Label(_("Antialiasing"))
        label.props.yalign = 0.0
        self.pack_start(label, False, False, 0)

        aa_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.pack_start(aa_box, False, False, 0)

        self.btn_rgba = Gtk.RadioButton.new_from_widget(None)
        self.btn_rgba.set_label(_("Subpixel (for LCD screens)"))
        self.btn_rgba.set_active(self.settings["font-antialiasing"] == "rgba")
        self.btn_rgba.connect("toggled", self.on_aa_button_toggled)
        aa_box.pack_start(self.btn_rgba, False, False, 0)

        self.btn_gray = Gtk.RadioButton.new_from_widget(self.btn_rgba)
        self.btn_gray.set_label(_("Standard (grayscale)"))
        self.btn_gray.set_active(
            self.settings["font-antialiasing"] == "grayscale")
        self.btn_gray.connect("toggled", self.on_aa_button_toggled)
        aa_box.pack_start(self.btn_gray, False, False, 0)

        self.btn_anone = Gtk.RadioButton.new_from_widget(self.btn_rgba)
        self.btn_anone.set_label(_("None"))
        self.btn_anone.set_active(self.settings["font-antialiasing"] == "none")
        self.btn_anone.connect("toggled", self.on_aa_button_toggled)
        aa_box.pack_start(self.btn_anone, False, False, 0)
예제 #17
0
class ShellThemeTweak(Gtk.Box, Tweak):

    THEME_EXT_NAME = "*****@*****.**"
    THEME_GSETTINGS_SCHEMA = "org.gnome.shell.extensions.user-theme"
    THEME_GSETTINGS_NAME = "name"
    THEME_GSETTINGS_DIR = os.path.join(GLib.get_user_data_dir(), "gnome-shell",
                                       "extensions", THEME_EXT_NAME, "schemas")
    LEGACY_THEME_DIR = os.path.join(GLib.get_home_dir(), ".themes")
    THEME_DIR = os.path.join(GLib.get_user_data_dir(), "themes")

    def __init__(self, **options):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
        Tweak.__init__(self, _("Shell theme"),
                       _("Install custom or user themes for gnome-shell"),
                       **options)

        #check the shell is running and the usertheme extension is present
        error = _("Unknown error")
        self._shell = _shell

        if self._shell is None:
            logging.warning("Shell not running", exc_info=True)
            error = _("Shell not running")
        else:
            try:
                extensions = self._shell.list_extensions()
                if ShellThemeTweak.THEME_EXT_NAME in extensions and extensions[
                        ShellThemeTweak.THEME_EXT_NAME]["state"] == 1:
                    #check the correct gsettings key is present
                    try:
                        if os.path.exists(ShellThemeTweak.THEME_GSETTINGS_DIR):
                            self._settings = GSettingsSetting(
                                ShellThemeTweak.THEME_GSETTINGS_SCHEMA,
                                schema_dir=ShellThemeTweak.THEME_GSETTINGS_DIR)
                        else:
                            self._settings = GSettingsSetting(
                                ShellThemeTweak.THEME_GSETTINGS_SCHEMA)
                        name = self._settings.get_string(
                            ShellThemeTweak.THEME_GSETTINGS_NAME)

                        ext = extensions[ShellThemeTweak.THEME_EXT_NAME]
                        logging.debug("Shell user-theme extension\n%s" %
                                      pprint.pformat(ext))

                        error = None
                    except:
                        logging.warning(
                            "Could not find user-theme extension in %s" %
                            ','.join(extensions.keys()),
                            exc_info=True)
                        error = _(
                            "Shell user-theme extension incorrectly installed")

                else:
                    error = _("Shell user-theme extension not enabled")
            except Exception, e:
                logging.warning("Could not list shell extensions",
                                exc_info=True)
                error = _("Could not list shell extensions")

        if error:
            cb = build_combo_box_text(None)
            build_label_beside_widget(self.name, cb, warning=error, hbox=self)
            self.widget_for_size_group = cb
        else:
            #include both system, and user themes
            #note: the default theme lives in /system/data/dir/gnome-shell/theme
            #      and not themes/, so add it manually later
            dirs = [
                os.path.join(d, "themes") for d in GLib.get_system_data_dirs()
            ]
            dirs += [ShellThemeTweak.THEME_DIR]
            dirs += [ShellThemeTweak.LEGACY_THEME_DIR]

            valid = walk_directories(dirs, lambda d:
                        os.path.exists(os.path.join(d, "gnome-shell")) and \
                        os.path.exists(os.path.join(d, "gnome-shell", "gnome-shell.css")))
            #the default value to reset the shell is an empty string
            valid.extend(("", ))

            #build a combo box with all the valid theme options
            #manually add Adwaita to represent the default
            cb = build_combo_box_text(
                self._settings.get_string(
                    ShellThemeTweak.THEME_GSETTINGS_NAME),
                *make_combo_list_with_default(
                    valid, "", default_text=_("<i>Default</i>")))
            cb.connect('changed', self._on_combo_changed)
            self._combo = cb

            #a filechooser to install new themes
            chooser = FileChooserButton(_("Select a theme"), True,
                                        ["application/zip"])
            chooser.connect("file-set", self._on_file_set)

            build_label_beside_widget(self.name, chooser, cb, hbox=self)
            self.widget_for_size_group = cb
예제 #18
0
class XSettingsOverrides:

    VARIANT_TYPES = {
        'Gtk/ShellShowsAppMenu': GLib.Variant.new_int32,
        'Gtk/EnablePrimaryPaste': GLib.Variant.new_int32,
        'Gdk/WindowScalingFactor': GLib.Variant.new_int32,
    }

    def __init__(self):
        # Ensure we don't error out
        try:
            self._settings = GSettingsSetting(
                schema='org.gnome.settings-daemon.plugins.xsettings')
        except:
            self._settings = None
            logging.warn(
                "org.gnome.settings-daemon.plugins.xsettings not installed or running"
            )

        if self._settings:
            self._variant = self._settings.get_value("overrides")

    def _dup_variant_as_dict(self):
        items = {}
        for k in list(self._variant.keys()):
            try:
                # variant override doesnt support .items()
                v = self._variant[k]
                items[k] = self.VARIANT_TYPES[k](v)
            except KeyError:
                pass
        return items

    def _dup_variant(self):
        return GLib.Variant('a{sv}', self._dup_variant_as_dict())

    def _set_override(self, name, v):
        items = self._dup_variant_as_dict()
        items[name] = self.VARIANT_TYPES[name](v)
        n = GLib.Variant('a{sv}', items)
        self._settings.set_value('overrides', n)
        self._variant = self._settings.get_value("overrides")

    def _get_override(self, name, default):
        try:
            return self._variant[name]
        except KeyError:
            return default

    # while I could store meta type information in the VARIANT_TYPES
    # dict, its easiest to do default value handling and missing value
    # checks in dedicated functions
    def set_shell_shows_app_menu(self, v):
        self._set_override('Gtk/ShellShowsAppMenu', int(v))

    def get_shell_shows_app_menu(self):
        return self._get_override('Gtk/ShellShowsAppMenu', True)

    def set_enable_primary_paste(self, v):
        self._set_override('Gtk/EnablePrimaryPaste', int(v))

    def get_enable_primary_paste(self):
        return self._get_override('Gtk/EnablePrimaryPaste', True)

    def set_window_scaling_factor(self, v):
        self._set_override('Gdk/WindowScalingFactor', int(v))

    def get_window_scaling_factor(self):
        return self._get_override('Gdk/WindowScalingFactor', 1)