/usr/lib/python2.7/dist-packages/gtweak/tweaks/tweak_shell_extensions.py
Code:
import os.path
import zipfile
import tempfile
import logging
import json
from gi.repository import Gtk
from gi.repository import GLib
from gtweak.utils import extract_zip_file
from gtweak.gshellwrapper import GnomeShell, GnomeShellFactory
from gtweak.tweakmodel import Tweak, TweakGroup
from gtweak.widgets import ZipFileChooserButton, build_label_beside_widget, build_horizontal_sizegroup
class _ShellExtensionTweak(Tweak):
def __init__(self, shell, ext, **options):
Tweak.__init__(self, ext["name"], ext.get("description",""), **options)
self._shell = shell
state = ext.get("state")
sw = Gtk.Switch()
sw.set_active(self._shell.extension_is_active(state, ext["uuid"]))
sw.connect('notify::active', self._on_extension_toggled, ext["uuid"])
warning = None
sensitive = False
if state == GnomeShell.EXTENSION_STATE["ENABLED"] or \
state == GnomeShell.EXTENSION_STATE["DISABLED"]:
sensitive = True
elif state == GnomeShell.EXTENSION_STATE["ERROR"]:
warning = _("Error loading extension")
elif state == GnomeShell.EXTENSION_STATE["OUT_OF_DATE"]:
warning = _("Extension does not support shell version")
else:
warning = _("Unknown extension error")
logging.critical(warning)
sw.set_sensitive(sensitive)
self.widget = build_label_beside_widget(
_("%s Extension") % ext["name"],
sw,
warning=warning)
self.widget_for_size_group = sw
def _on_extension_toggled(self, sw, active, uuid):
if not sw.get_active():
self._shell.disable_extension(uuid)
else:
self._shell.enable_extension(uuid)
if self._shell.EXTENSION_NEED_RESTART:
self.notify_action_required(
_("The shell must be restarted for changes to take effect"),
_("Restart"),
self._shell.restart)
class _ShellExtensionInstallerTweak(Tweak):
EXTENSION_DIR = os.path.join(GLib.get_user_data_dir(), "gnome-shell", "extensions")
def __init__(self, shell, **options):
Tweak.__init__(self, _("Install Shell Extension"), "", **options)
self._shell = shell
chooser = ZipFileChooserButton(_("Select an extension"))
chooser.connect("file-set", self._on_file_set)
self.widget = build_label_beside_widget(self.name, chooser)
self.widget_for_size_group = chooser
def _on_file_set(self, chooser):
f = chooser.get_filename()
with zipfile.ZipFile(f, 'r') as z:
try:
fragment = ()
file_extension = None
file_metadata = None
for n in z.namelist():
if n.endswith("metadata.json"):
fragment = n.split("/")[0:-1]
file_metadata = n
if n.endswith("extension.js"):
if file_extension:
raise Exception("Only one extension per zip file")
file_extension = n
if not file_metadata:
raise Exception("Could not find metadata.json")
if not file_extension:
raise Exception("Could not find extension.js")
#extract the extension uuid
extension_uuid = None
tmp = tempfile.mkdtemp()
z.extract(file_metadata, tmp)
with open(os.path.join(tmp, file_metadata)) as f:
try:
extension_uuid = json.load(f)["uuid"]
except:
logging.warning("Invalid extension format", exc_info=True)
ok = False
if extension_uuid:
ok, updated = extract_zip_file(
z,
"/".join(fragment),
os.path.join(self.EXTENSION_DIR, extension_uuid))
if ok:
if updated:
verb = _("%s extension updated successfully") % extension_uuid
else:
verb = _("%s extension installed successfully") % extension_uuid
self.notify_action_required(
verb,
_("Restart"),
self._shell.restart)
else:
self.notify_error(_("Error installing extension"))
except:
#does not look like a valid theme
self.notify_error(_("Invalid extension"))
logging.warning("Error parsing theme zip", exc_info=True)
#set button back to default state
chooser.unselect_all()
class ShellExtensionTweakGroup(TweakGroup):
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)
TWEAK_GROUPS = (
ShellExtensionTweakGroup(),
)
/usr/lib/python2.7/dist-packages/gtweak/gshellwrapper.py
Code:
# This file is part of gnome-tweak-tool.
#
# Copyright (c) 2011 John Stowers
#
# gnome-tweak-tool is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gnome-tweak-tool is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gnome-tweak-tool. If not, see <http://www.gnu.org/licenses/>.
import os.path
import json
import logging
from gi.repository import Gio
from gi.repository import GLib
import gtweak.utils
from gtweak.gsettings import GSettingsSetting
class _ShellProxy:
def __init__(self):
d = Gio.bus_get_sync(Gio.BusType.SESSION, None)
self.proxy = Gio.DBusProxy.new_sync(
d, 0, None,
'org.gnome.Shell',
'/org/gnome/Shell',
'org.gnome.Shell',
None)
def execute_js(self, js):
result, output = self.proxy.Eval('(s)', js)
if not result:
raise Exception(output)
return output
@property
def version(self):
return json.loads(self.execute_js('const Config = imports.misc.config; Config.PACKAGE_VERSION'))
class GnomeShell:
EXTENSION_STATE = {
"ENABLED" : 1,
"DISABLED" : 2,
"ERROR" : 3,
"OUT_OF_DATE" : 4,
"DISABLED" : 6
}
EXTENSION_TYPE = {
"SYSTEM" : 1,
"PER_USER" : 2
}
DATA_DIR = os.path.join(GLib.get_user_data_dir(), "gnome-shell")
def __init__(self, shellproxy, shellsettings):
self._proxy = shellproxy
self._settings = shellsettings
def restart(self):
self._proxy.execute_js('global.reexec_self();')
def reload_theme(self):
self._proxy.execute_js('const Main = imports.ui.main; Main.loadTheme();')
@property
def version(self):
return self._proxy.version
class GnomeShell30(GnomeShell):
EXTENSION_DISABLED_KEY = "disabled-extensions"
EXTENSION_NEED_RESTART = True
def __init__(self, *args, **kwargs):
GnomeShell.__init__(self, *args, **kwargs)
def list_extensions(self):
out = self._proxy.execute_js('const ExtensionSystem = imports.ui.extensionSystem; ExtensionSystem.extensionMeta')
return json.loads(out)
def extension_is_active(self, state, uuid):
return state == GnomeShell.EXTENSION_STATE["ENABLED"] and \
not self._settings.setting_is_in_list(self.EXTENSION_DISABLED_KEY, uuid)
def enable_extension(self, uuid):
self._settings.setting_remove_from_list(self.EXTENSION_DISABLED_KEY, uuid)
def disable_extension(self, uuid):
self._settings.setting_add_to_list(self.EXTENSION_DISABLED_KEY, uuid)
class GnomeShell32(GnomeShell):
EXTENSION_ENABLED_KEY = "enabled-extensions"
EXTENSION_NEED_RESTART = False
def list_extensions(self):
return self._proxy.proxy.ListExtensions()
def extension_is_active(self, state, uuid):
return state == GnomeShell.EXTENSION_STATE["ENABLED"] and \
self._settings.setting_is_in_list(self.EXTENSION_ENABLED_KEY, uuid)
def enable_extension(self, uuid):
self._settings.setting_add_to_list(self.EXTENSION_ENABLED_KEY, uuid)
def disable_extension(self, uuid):
self._settings.setting_remove_from_list(self.EXTENSION_ENABLED_KEY, uuid)
@gtweak.utils.singleton
class GnomeShellFactory:
def __init__(self):
proxy = _ShellProxy()
settings = GSettingsSetting("org.gnome.shell")
v = map(int,proxy.version.split("."))
if v >= [3,1,4]:
self.shell = GnomeShell32(proxy, settings)
else:
self.shell = GnomeShell30(proxy, settings)
logging.debug("Shell version: %s", str(v))
def get_shell(self):
return self.shell
if __name__ == "__main__":
gtweak.GSETTINGS_SCHEMA_DIR = "/usr/share/glib-2.0/schemas/"
s = GnomeShellFactory().get_shell()
print "Shell Version: %s" % s.version
print s.list_extensions()
print s == GnomeShellFactory().get_shell()
/usr/lib/python2.7/dist-packages/gtweak/gsettings.py
Code:
# This file is part of gnome-tweak-tool.
#
# Copyright (c) 2011 John Stowers
#
# gnome-tweak-tool is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gnome-tweak-tool is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gnome-tweak-tool. If not, see <http://www.gnu.org/licenses/>.
import logging
import os.path
import xml.dom.minidom
import gtweak
from gi.repository import Gio, GLib
class _GSettingsSchema:
def __init__(self, schema_name, schema_dir=None, schema_filename=None, **options):
if not schema_dir:
schema_dir = gtweak.GSETTINGS_SCHEMA_DIR
if not schema_filename:
schema_filename = schema_name + ".gschema.xml"
schema_path = os.path.join(schema_dir, schema_filename)
assert(os.path.exists(schema_path))
self._schema_name = schema_name
self._schema = {}
try:
dom = xml.dom.minidom.parse(schema_path)
for schema in dom.getElementsByTagName("schema"):
if schema_name == schema.getAttribute("id"):
for key in schema.getElementsByTagName("key"):
#summary is compulsory, description is optional
try:
summary = key.getElementsByTagName("summary")[0].childNodes[0].data
description = key.getElementsByTagName("description")[0].childNodes[0].data
except:
description = ""
summary = "No Summary"
self._schema[key.getAttribute("name")] = {
"summary" : summary,
"description" : description
}
except:
logging.critical("Error parsing schema %s (%s)" % (schema_name, schema_path), exc_info=True)
def __repr__(self):
return "<gtweak.gsettings._GSettingsSchema: %s>" % self._schema_name
_SCHEMA_CACHE = {}
class GSettingsSetting(Gio.Settings):
def __init__(self, schema_name, **options):
Gio.Settings.__init__(self, schema_name)
if schema_name not in _SCHEMA_CACHE:
_SCHEMA_CACHE[schema_name] = _GSettingsSchema(schema_name, **options)
logging.debug("Caching gsettings: %s" % _SCHEMA_CACHE[schema_name])
self._schema = _SCHEMA_CACHE[schema_name]
if gtweak.VERBOSE:
self.connect("changed", self._on_changed)
def _on_changed(self, settings, key_name):
print "Change: %s %s -> %s" % (self.props.schema, key_name, self[key_name])
def _setting_check_is_list(self, key):
variant = Gio.Settings.get_value(self, key)
return variant.get_type_string() == "as"
def schema_get_summary(self, key):
return self._schema._schema[key]["summary"]
def schema_get_description(self, key):
return self._schema._schema[key]["description"]
def schema_get_all(self, key):
return self._schema._schema[key]
def setting_add_to_list(self, key, value):
""" helper function, ensures value is present in the GSettingsList at key """
assert self._setting_check_is_list(key)
vals = self[key]
if value not in vals:
vals.append(value)
self[key] = vals
return True
def setting_remove_from_list(self, key, value):
""" helper function, removes value in the GSettingsList at key (if present)"""
assert self._setting_check_is_list(key)
vals = self[key]
try:
vals.remove(value)
self[key] = vals
return True
except ValueError:
#not present
pass
def setting_is_in_list(self, key, value):
assert self._setting_check_is_list(key)
return value in self[key]
if __name__ == "__main__":
gtweak.GSETTINGS_SCHEMA_DIR = "/usr/share/glib-2.0/schemas/"
key = "draw-background"
s = GSettingsSetting("org.gnome.desktop.background")
print s.schema_get_summary(key), s.schema_get_description(key)
key = "disabled-extensions"
s = GSettingsSetting("org.gnome.shell")
assert s.setting_add_to_list(key, "foo")
assert s.setting_remove_from_list(key, "foo")
assert not s.setting_remove_from_list(key, "foo")
P.S. I edited files (from your posts above) with command: $sudo gedit ...
I don't know if that is right, please notice that I'm great noob for linux, been using windows since Win95.
Bookmarks