def __init__(self):
        TweakGroup.__init__(self, _("Shell Extensions"))

        extension_tweaks = []
        sg = build_horizontal_sizegroup()

        #check the shell is running
        try:
            shell = GnomeShellFactory().get_shell()

            #add the extension installer
            extension_tweaks.append(
                _ShellExtensionInstallerTweak(shell, size_group=sg))

            try:
                #add a tweak for each installed extension
                for extension in shell.list_extensions().values():
                    try:
                        extension_tweaks.append(
                            _ShellExtensionTweak(shell, extension, size_group=sg))
                    except:
                        logging.warning("Invalid extension", exc_info=True)
            except:
                logging.warning("Error listing extensions", exc_info=True)
        except:
            logging.warning("Error detecting shell", exc_info=True)

        self.set_tweaks(*extension_tweaks)
Exemplo n.º 2
0
    def __init__(self):
        extension_tweaks = []
        sg = build_horizontal_sizegroup()

        #check the shell is running
        try:
            shell = GnomeShellFactory().get_shell()
            if shell is None:
                raise Exception(
                    "Shell not running or DBus service not available")

            version = tuple(shell.version.split("."))
            ego = ExtensionsDotGnomeDotOrg(version)
            try:
                #add a tweak for each installed extension
                extensions = sorted(list(shell.list_extensions().values()),
                                    key=itemgetter("name"))
                for extension in extensions:
                    try:
                        extension_widget = _ShellExtensionTweak(shell,
                                                                extension,
                                                                size_group=sg)
                        extension_tweaks.append(extension_widget)
                        if extension.get("type") == GnomeShell.EXTENSION_TYPE[
                                "PER_USER"]:
                            ego.connect("got-extension-info", self._got_info,
                                        extension, extension_widget)
                            ego.query_extension_info(extension["uuid"])
                    except:
                        logging.warning("Invalid extension", exc_info=True)
            except:
                logging.warning("Error listing extensions", exc_info=True)
        except:
            logging.warning("Error detecting shell", exc_info=True)

        ListBoxTweakGroup.__init__(self,
                                   _("Extensions"),
                                   *extension_tweaks,
                                   activatable=True)

        if shell is None:
            return  # we're done

        self.props.valign = Gtk.Align.FILL

        self.titlebar_widget = Gtk.Switch(visible=True)
        shell._settings.bind("disable-user-extensions", self.titlebar_widget,
                             "active", Gio.SettingsBindFlags.INVERT_BOOLEAN)

        self.set_header_func(self._list_header_func, None)
        self.connect("row-activated", self._on_row_activated, None)

        if not len(extension_tweaks):
            placeholder = _ExtensionsBlankState()
            self.set_placeholder(placeholder)
            self.tweaks.append(placeholder)
Exemplo n.º 3
0
    def about_cb(self, action, parameter):
        aboutdialog = Gtk.AboutDialog(modal=True, transient_for=self.win)
        aboutdialog.set_program_name(aboutdialog.get_program_name() +
                                     " %s" % VERSION)

        _shell = GnomeShellFactory().get_shell()
        if _shell is not None:
            if _shell.mode == "user":
                about_comment = _("GNOME Shell") + " %s" % _shell.version
            else:
                about_comment = (_("GNOME Shell") + " %s " + _("(%s mode)")) % \
                    (_shell.version, _shell.mode)
        else:
            about_comment = _("GNOME Shell is not running")

        about_comment += "\n" + _("GTK") + " %d.%d.%d" % \
            (Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version())
        aboutdialog.set_comments(about_comment)

        aboutdialog.set_copyright("Copyright © 2011 - 2013 John Stowers.")
        aboutdialog.set_logo_icon_name("org.gnome.tweaks")
        aboutdialog.set_website("https://wiki.gnome.org/Apps/Tweaks")
        aboutdialog.set_website_label(_("Homepage"))
        aboutdialog.set_license_type(Gtk.License.GPL_3_0)

        AUTHORS = ["John Stowers <*****@*****.**>"]

        aboutdialog.set_authors(AUTHORS)
        aboutdialog.connect("response", lambda w, r: aboutdialog.destroy())
        aboutdialog.show()
Exemplo n.º 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 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")
    def __init__(self):
        extension_tweaks = []
        sg = build_horizontal_sizegroup()

        #check the shell is running
        try:
            shell = GnomeShellFactory().get_shell()
            if shell is None:
                raise Exception(
                    "Shell not running or DBus service not available")

            version = tuple(shell.version.split("."))
            ego = ExtensionsDotGnomeDotOrg(version)
            try:
                #add a tweak for each installed extension
                extensions = sorted(shell.list_extensions().values(),
                                    key=itemgetter("name"))
                for extension in extensions:
                    try:
                        extension_widget = _ShellExtensionTweak(shell,
                                                                extension,
                                                                size_group=sg)
                        extension_tweaks.append(extension_widget)
                        if extension.get("type") == GnomeShell.EXTENSION_TYPE[
                                "PER_USER"]:
                            ego.connect("got-extension-info", self._got_info,
                                        extension, extension_widget)
                            ego.query_extension_info(extension["uuid"])
                    except:
                        logging.warning("Invalid extension", exc_info=True)
            except:
                logging.warning("Error listing extensions", exc_info=True)
        except:
            logging.warning("Error detecting shell", exc_info=True)

        #add the extension installer
        extension_tweaks.append(
            _ShellExtensionInstallerTweak(shell, size_group=sg))

        ListBoxTweakGroup.__init__(self, _("Extensions"), *extension_tweaks)

        self.set_header_func(self._list_header_func, None)
    def _got_info(self, ego, resp, uuid, extension, widget):
        if uuid == extension["uuid"]:
            resp = resp['shell_version_map']
            shell = GnomeShellFactory().get_shell()
            version = shell.version[0:3]
            try:
                resp = resp[version]
                if int(resp["version"]) > extension["version"]:
                    widget.add_update_button(uuid)

            except KeyError:
                print "Older/Unknown Version"
    def __init__(self):
        extension_tweaks = []
        sg = build_horizontal_sizegroup()

        #check the shell is running
        try:
            shell = GnomeShellFactory().get_shell()
            if shell is None:
                raise Exception("Shell not running or DBus service not available")

            version =  tuple(shell.version.split("."))
            ego = ExtensionsDotGnomeDotOrg(version)
            try:
                #add a tweak for each installed extension
                extensions = sorted(shell.list_extensions().values(), key=itemgetter("name"))
                for extension in extensions:
                    try:
                        extension_widget = _ShellExtensionTweak(shell, extension, size_group=sg)
                        extension_tweaks.append(extension_widget)
                        if extension.get("type") == GnomeShell.EXTENSION_TYPE["PER_USER"]:
                            ego.connect("got-extension-info", self._got_info, extension, extension_widget)
                            ego.query_extension_info(extension["uuid"])
                    except:
                        logging.warning("Invalid extension", exc_info=True)
            except:
                logging.warning("Error listing extensions", exc_info=True)
        except:
            logging.warning("Error detecting shell", exc_info=True)
        
        #add the extension installer
        extension_tweaks.append(
                _ShellExtensionInstallerTweak(shell, size_group=sg))
            
        ListBoxTweakGroup.__init__(self,
                                   _("Extensions"),
                                   *extension_tweaks)
        
        self.set_header_func(self._list_header_func, None)
    def _got_info(self, ego, resp, uuid, extension, widget):
        if uuid == extension["uuid"]:
            resp = resp['shell_version_map']
            shell = GnomeShellFactory().get_shell()
            version = _fix_shell_version_for_ego(shell.version)
            try:
                resp = resp[version]
                if int(resp["version"]) > extension["version"]:
                    widget.add_update_button(uuid)

            except KeyError:
                logging.info(
                    "e.g.o no updates for %s (shell version %s extension version %s)"
                    % (uuid, version, extension["version"]))
Exemplo n.º 9
0
    def _got_info(self, ego, resp, uuid, extension, widget):
        if uuid == extension["uuid"]:
            resp = resp['shell_version_map']
            shell = GnomeShellFactory().get_shell()
            version = _fix_shell_version_for_ego(shell.version)

            if version in resp:
                resp = resp[version]
                ext_version = extension["version"] if "version" in extension else 0
                if int(resp["version"]) > ext_version:
                    widget.add_update_button(uuid)
            else:
                ext_version = extension["version"] if "version" in extension else "unknown"
                logging.info("e.g.o no updates for %s (shell version %s extension version %s)" % (
                             uuid, version, ext_version))
Exemplo n.º 10
0
    def about_cb(self, action, parameter):
        aboutdialog = Gtk.AboutDialog()

        _shell = GnomeShellFactory().get_shell()
        if _shell is not None:
            aboutdialog.set_comments(
                _("GNOME Shell v%s (%s mode)") % (_shell.version, _shell.mode))
        else:
            aboutdialog.set_comments(_("GNOME Shell not running"))

        aboutdialog.set_copyright(
            "Copyright \xc2\xa9 2011 - 2013 John Stowers.")
        aboutdialog.set_logo_icon_name("gnome-tweak-tool")
        aboutdialog.set_website("http://live.gnome.org/GnomeTweakTool")
        aboutdialog.set_website_label(_("Homepage"))
        aboutdialog.set_license_type(Gtk.License.GPL_3_0)

        AUTHORS = ["John Stowers <*****@*****.**>"]

        aboutdialog.set_authors(AUTHORS)
        aboutdialog.connect("response", lambda w, r: aboutdialog.destroy())
        aboutdialog.show()
Exemplo n.º 11
0
import zipfile
import tempfile
import json
import pprint

from gi.repository import Gtk
from gi.repository import GLib

import gtweak
from gtweak.utils import walk_directories, make_combo_list_with_default, extract_zip_file
from gtweak.tweakmodel import Tweak, TWEAK_GROUP_APPEARANCE
from gtweak.gshellwrapper import GnomeShellFactory
from gtweak.gsettings import GSettingsSetting
from gtweak.widgets import ListBoxTweakGroup, GSettingsSwitchTweak, GSettingsComboTweak, DarkThemeSwitcher, Title, build_combo_box_text, build_label_beside_widget, FileChooserButton

_shell = GnomeShellFactory().get_shell()
_shell_loaded = _shell is not None


class GtkThemeSwitcher(GSettingsComboTweak):
    def __init__(self, **options):
        GSettingsComboTweak.__init__(
            self, "GTK+", "org.gnome.desktop.interface", "gtk-theme",
            make_combo_list_with_default(self._get_valid_themes(), "Adwaita"),
            **options)

    def _get_valid_themes(self):
        """ Only shows themes that have variations for gtk+-3 and gtk+-2 """
        gtk_ver = Gtk.MINOR_VERSION
        if gtk_ver % 2:  # Want even number
            gtk_ver += 1
Exemplo n.º 12
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
Exemplo n.º 13
0
class ShellThemeTweak(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")
    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 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:
                    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)
            self.widget = build_label_beside_widget(self.name, cb, warning=error)
            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]

            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 = ZipFileChooserButton(_("Select a theme"))
            chooser.connect("file-set", self._on_file_set)

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