diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile.am | 15 | ||||
-rwxr-xr-x | tools/mate-conf-import | 507 | ||||
-rw-r--r-- | tools/mate-conf-import.desktop.in.in | 10 |
3 files changed, 530 insertions, 2 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am index 399fb83..65faf6d 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,3 +1,14 @@ -bin_SCRIPTS = mate-gsettings-toggle.sh +bin_SCRIPTS = mate-gsettings-toggle -EXTRA_DIST = $(bin_SCRIPTS) +if MATE_CONF_IMPORT_ENABLED +@INTLTOOL_DESKTOP_RULE@ + +desktopdir = $(datadir)/applications +desktop_in_files = mate-conf-import.desktop.in +desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) +bin_SCRIPTS += mate-conf-import +endif + +EXTRA_DIST = $(bin_SCRIPTS) + +CLEANFILES = mate-conf-import.desktop diff --git a/tools/mate-conf-import b/tools/mate-conf-import new file mode 100755 index 0000000..beb7976 --- /dev/null +++ b/tools/mate-conf-import @@ -0,0 +1,507 @@ +#!/usr/bin/env python +# +# Copyright (c) 2013 Stefano Karapetsas +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program 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 Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# +# Authors: Stefano Karapetsas <[email protected]> + +import glob +import optparse +import os +import sys + +# to read MateConf files +import xml.etree.ElementTree as ElementTree + +# gobject introspection +import gi +# to show dialogs +gi.require_version("Gtk", "2.0") +from gi.repository import Gtk +# to read convert files +from gi.repository import GLib +# to write GSettings +from gi.repository import Gio + +# command options +parser = optparse.OptionParser() +parser.add_option("-d", "--debug", dest="debug", action="store_true", help="enable debug messages") +parser.add_option("-f", "--force", dest="force", action="store_true", help="force migration of settings") +parser.add_option("-l", "--linuxmint", dest="linuxmint", action="store_true", help="force detection of linuxmint") +(options, args) = parser.parse_args() + +# print a message only if debug option is enabled +def debug_message(*argv): + args = [] + for arg in argv: + args.append(str(arg)) + if options.debug: + print " ".join(args) + +# get a mateconf string list +def mateconf_get_string_list(root, key): + for child in root: + if child.attrib['name'] == key: + if child.attrib["type"] == "list": + if child.attrib["ltype"] == "string": + if len(list(child)) > 0: + strv = [] + for ch in child: + for li in ch: + strv.append(li.text) + return strv + else: + return [] + return None + +def gsettings_id(id): + return id.replace("_", "-") + +mateconf_user_path = os.path.dirname(os.path.join(GLib.get_home_dir(), ".mateconf/")) +if not os.path.exists(mateconf_user_path): + #FIXME save key in GSettings + debug_message(mateconf_user_path, "not found!") + sys.exit(0) + +#FIXME check GSettings key +dialog = Gtk.MessageDialog (None, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.QUESTION, + Gtk.ButtonsType.YES_NO, + "Are you sure to migrate settings from MATE 1.4?\n" + \ + "This will delete permanently all your current 1.6 settings.") +res = dialog.run() +if res != Gtk.ResponseType.YES: + dialog.destroy() + sys.exit(0) +dialog.destroy() + +# load .convert files list from MateConf folder +convert_files = glob.glob("/usr/share/MateConf/gsettings/*") + +no_background = False +for convert_file in convert_files: + + # load .convert file + keyfile = GLib.KeyFile.new() + GLib.KeyFile.load_from_file(keyfile, convert_file, 0) + groups = GLib.KeyFile.get_groups(keyfile) + + # iter GSettings schemas + for group in groups[0]: + + # each group is a GSettings schema + gsettings_schema = group + keys = GLib.KeyFile.get_keys(keyfile, group); + settings = Gio.Settings.new(gsettings_schema) + + # delay settings to save them only once + settings.delay() + + # iter GSettings keys + for gsettings_key in keys[0]: + + # get mateconf xml file, + mateconf_fullkey = GLib.KeyFile.get_string(keyfile, group, gsettings_key) + mateconf_path = os.path.dirname(os.path.join(mateconf_user_path, mateconf_fullkey[1:])) + mateconf_file = os.path.join(mateconf_path, "%mateconf.xml") + mateconf_key = os.path.basename(mateconf_fullkey) + + # if user has custom mateconf + if os.path.exists(mateconf_file): + + # MateConf file could be empty + try: + tree = ElementTree.parse(mateconf_file) + root = tree.getroot() + except: + continue + + for child in root: + # if the key exists, the user has a custom value + if child.attrib['name'] == mateconf_key: + + # boolean + if child.attrib["type"] == "bool": + if child.attrib["value"] == "true": + debug_message(gsettings_schema, gsettings_key, True) + settings.set_boolean(gsettings_key, True) + else: + debug_message(gsettings_schema, gsettings_key, False) + settings.set_boolean(gsettings_key, False) + + # int + elif child.attrib["type"] == "int": + debug_message(gsettings_schema, gsettings_key, int(child.attrib["value"])) + settings.set_int(gsettings_key, int(child.attrib["value"])) + + # string + elif child.attrib["type"] == "string": + + value = child[0].text + # hack for background + if gsettings_schema == "org.mate.background" and gsettings_key == "picture-filename": + # check if the background exists before apply it + if not os.path.exists(value): + if "/pixmaps/backgrounds/" in value: + value = value.replace("/pixmaps/backgrounds/", "/backgrounds/") + if not os.path.exists(value): + no_background = True + continue + else: + no_background = True + continue + if no_background and gsettings_schema == "org.mate.background": + continue + + if value != None: + debug_message(gsettings_schema, gsettings_key, value) + settings.set_string(gsettings_key, value) + + # list + elif child.attrib["type"] == "list": + + # list of strings + if child.attrib["ltype"] == "string": + + if len(list(child)) > 0: + strv = [] + for ch in child: + for li in ch: + strv.append(li.text) + debug_message(gsettings_schema, gsettings_key, strv) + settings.set_strv(gsettings_key, strv) + else: + debug_message(gsettings_schema, gsettings_key, "[]") + settings.set_strv(gsettings_key, []) + else: + debug_message("Unknown list type", child.attrib["ltype"]) + + else: + debug_message("Unknown type", child.attrib["type"]) + + settings.apply() + +# ugly hack to migrate panel layout +is_linuxmint = os.path.exists("/etc/linuxmint/info") or options.linuxmint +mateconf_panel_file = os.path.join(mateconf_user_path, "apps/panel/general", "%mateconf.xml") +if os.path.exists(mateconf_panel_file): + + # load list of panels + tree = ElementTree.parse(mateconf_panel_file) + root = tree.getroot() + + # old lists + toplevels = mateconf_get_string_list (root, "toplevel_id_list") + objects = mateconf_get_string_list (root, "object_id_list") + applets = mateconf_get_string_list (root, "applet_id_list") + + panel_settings = Gio.Settings.new("org.mate.panel") + panel_settings.delay() + + # new lists (applets are together with objects in 1.6) + new_toplevels = [] + new_objects = [] + new_applets_without_toplevel = [] + new_bottom_toplevel = None + new_top_toplevel = None + + # import objects + for obj in objects: + debug_message("object", obj) + mateconf_obj_file = os.path.join(mateconf_user_path, "apps/panel/objects", obj, "%mateconf.xml") + if not os.path.exists(mateconf_obj_file): + debug_message ("object", obj, "mateconf file not found!") + continue + try: + obj_tree = ElementTree.parse(mateconf_obj_file) + obj_root = obj_tree.getroot() + except: + debug_message ("object", obj, "mateconf file invalid!") + continue + obj_id = gsettings_id(obj) + obj_settings = Gio.Settings.new_with_path("org.mate.panel.object", "/org/mate/panel/objects/%s/" % obj_id) + new_objects.append(obj_id) + + for child in obj_root: + # toplevel-id + if child.attrib["name"] == "toplevel_id": + obj_settings.set_string("toplevel-id", gsettings_id(child[0].text)) + # object-type + elif child.attrib["name"] == "object_type": + obj_type = child[0].text + # changed types in 1.6 + if obj_type == "launcher-object": + obj_type = "launcher" + elif obj_type == "action-applet": + obj_type = "action" + elif obj_type == "drawer-object": + obj_type = "drawer" + obj_settings.set_string("object-type", obj_type) + # other settings + elif "type" in child.attrib: + name = gsettings_id(child.attrib["name"]) + # boolean + if child.attrib["type"] == "bool": + if child.attrib["value"] == "true": + obj_settings.set_boolean(name, True) + else: + obj_settings.set_boolean(name, False) + # int + elif child.attrib["type"] == "int": + obj_settings.set_int(name, int(child.attrib["value"])) + # string + elif child.attrib["type"] == "string": + obj_settings.set_string(name, child[0].text) + + # import applets + for app in applets: + debug_message("applet", app) + mateconf_app_file = os.path.join(mateconf_user_path, "apps/panel/applets", app, "%mateconf.xml") + if not os.path.exists(mateconf_app_file): + debug_message ("applet", app, "mateconf file not found!") + try: + app_tree = ElementTree.parse(mateconf_app_file) + app_root = app_tree.getroot() + except: + debug_message ("applet", app, "mateconf file invalid!") + # empty mateconf file, try to create an applet + # FIXME: we should add default applets with their values + # this means use default 1.4 layout, except for linuxmint + # (that should be the only distribution with a custom panel layout) + applet_iid = None + right_stick = False + position = 0 + # if you add an applet here, add also the same iid couple later + if "showdesktop" in app: + applet_iid = "WnckletFactory::ShowDesktopApplet" + elif "notification" in app: + applet_iid = "NotificationAreaAppletFactory::NotificationArea" + right_stick = True + position = 10 + elif "clock" in app: + applet_iid = "ClockAppletFactory::ClockApplet" + right_stick = True + elif "windowlist" in app: + applet_iid = "WnckletFactory::WindowListApplet" + position = 10 + elif "mintmenu" in app: + applet_iid = "MintMenuAppletFactory::MintMenuApplet" + if applet_iid != None: + debug_message ("applet", app, "try to create as '%s'" % applet_iid) + app_id = gsettings_id(app) + app_settings = Gio.Settings.new_with_path("org.mate.panel.object", "/org/mate/panel/objects/%s/" % app_id) + new_objects.append(app_id) + new_applets_without_toplevel.append(app_id) + app_settings.set_string("object-type", "applet") + app_settings.set_string("applet-iid", applet_iid) + app_settings.set_boolean("panel-right-stick", right_stick) + app_settings.set_int("position", position) + continue + app_id = gsettings_id(app) + app_settings = Gio.Settings.new_with_path("org.mate.panel.object", "/org/mate/panel/objects/%s/" % app_id) + new_objects.append(app_id) + + applet_iid = None + toplevel_id = None + app_type = None + for child in app_root: + # toplevel-id + if child.attrib["name"] == "toplevel_id": + toplevel_id = gsettings_id(child[0].text) + app_settings.set_string("toplevel-id", toplevel_id) + # object-type + elif child.attrib["name"] == "object_type": + app_type = child[0].text + if app_type == "external-applet": + app_type = "applet" + elif app_type == "matecomponent-applet": + app_type = "applet" + app_settings.set_string("object-type", app_type) + # applet-iid + elif child.attrib["name"] == "applet_iid": + applet_iid = child[0].text + # changed iids in 1.6 + if applet_iid == "OAFIID:SensorsApplet": + applet_iid = "SensorsAppletFactory::SensorsApplet" + elif applet_iid == "OAFIID:MATE_NetspeedApplet": + applet_iid = "NetspeedAppletFactory::NetspeedApplet" + elif applet_iid == "OAFIID:MATE_DictionaryApplet": + applet_iid = "DictionaryAppletFactory::DictionaryApplet" + elif applet_iid == "OAFIID:Invest_Applet": + applet_iid = "InvestAppletFactory::InvestApplet" + elif applet_iid == "OAFIID:MATE_DictionaryApplet": + applet_iid = "DictionaryAppletFactory::DictionaryApplet" + elif applet_iid == "OAFIID:MATE_InhibitApplet": + applet_iid = "InhibitAppletFactory::InhibitApplet" + elif applet_iid == "OAFIID:TimerApplet": + # not yet ready in 1.6 :( + applet_iid = "TimerAppletFactory::TimerApplet" + debug_message ("applet", app, "is '%s'" % applet_iid) + app_settings.set_string("applet-iid", applet_iid) + # other settings + elif "type" in child.attrib: + name = gsettings_id(child.attrib["name"]) + # boolean + if child.attrib["type"] == "bool": + if child.attrib["value"] == "true": + app_settings.set_boolean(name, True) + else: + app_settings.set_boolean(name, False) + # int + elif child.attrib["type"] == "int": + app_settings.set_int(name, int(child.attrib["value"])) + # string + elif child.attrib["type"] == "string": + app_settings.set_string(name, child[0].text) + + # applet-iid could be missing if it is a default applet, but the + # user changes some values of it (for example, position) + if applet_iid == None: + if "showdesktop" in app: + applet_iid = "WnckletFactory::ShowDesktopApplet" + elif "notification" in app: + applet_iid = "NotificationAreaAppletFactory::NotificationArea" + elif "clock" in app: + applet_iid = "ClockAppletFactory::ClockApplet" + elif "windowlist" in app: + applet_iid = "WnckletFactory::WindowListApplet" + elif "mintmenu" in app: + applet_iid = "MintMenuAppletFactory::MintMenuApplet" + if applet_iid != None: + debug_message ("applet", app, "id was missing: '%s'" % applet_iid) + app_settings.set_string("applet-iid", applet_iid) + + if toplevel_id == None: + new_applets_without_toplevel.append(app_id) + if app_type == None: + app_settings.set_string("object-type", "applet") + + # import panels + for toplevel in toplevels: + debug_message("toplevel", toplevel) + mateconf_toplevel_file = os.path.join(mateconf_user_path, "apps/panel/toplevels", toplevel, "%mateconf.xml") + if not os.path.exists(mateconf_toplevel_file): + debug_message ("toplevel", toplevel, "mateconf file not found!") + try: + toplevel_tree = ElementTree.parse(mateconf_toplevel_file) + toplevel_root = toplevel_tree.getroot() + except: + # empty mateconf file, it's a default panel + debug_message ("toplevel", toplevel, "mateconf file invalid, creating as default!") + toplevel_id = gsettings_id(toplevel) + toplevel_settings = Gio.Settings.new_with_path("org.mate.panel.toplevel", "/org/mate/panel/toplevels/%s/" % toplevel_id) + if is_linuxmint: + toplevel_settings.set_string("orientation", "bottom") + else: + toplevel_settings.set_string("orientation", "top") + new_toplevels.append(toplevel_id) + continue + + toplevel_id = gsettings_id(toplevel) + toplevel_settings = Gio.Settings.new_with_path("org.mate.panel.toplevel", "/org/mate/panel/toplevels/%s/" % toplevel_id) + new_toplevels.append(toplevel_id) + + for child in toplevel_root: + if "type" in child.attrib: + name = gsettings_id(child.attrib["name"]) + if name == "orientation": + if child[0].text == "top": + new_top_toplevel = toplevel_id + elif child[0].text == "bottom": + new_bottom_toplevel = toplevel_id + # boolean + if child.attrib["type"] == "bool": + if child.attrib["value"] == "true": + toplevel_settings.set_boolean(name, True) + else: + toplevel_settings.set_boolean(name, False) + # int + elif child.attrib["type"] == "int": + toplevel_settings.set_int(name, int(child.attrib["value"])) + # string + elif child.attrib["type"] == "string": + toplevel_settings.set_string(name, child[0].text) + + # set created applets to first toplevel + for app_id in new_applets_without_toplevel: + app_settings = Gio.Settings.new_with_path("org.mate.panel.object", "/org/mate/panel/objects/%s/" % app_id) + if is_linuxmint and (new_bottom_toplevel != None): + app_settings.set_string("toplevel-id", new_bottom_toplevel) + else: + app_settings.set_string("toplevel-id", new_toplevels[0]) + + # set new toplevels and objects + panel_settings.set_strv("toplevel-id-list", new_toplevels) + panel_settings.set_strv("object-id-list", new_objects) + + # apply settings! + panel_settings.apply() + +# ugly hack to migrate terminal default profile +mateconf_terminal_file = os.path.join(mateconf_user_path, "apps/mate-terminal/profiles/Default", "%mateconf.xml") +if os.path.exists(mateconf_terminal_file): + + tree = ElementTree.parse(mateconf_terminal_file) + root = tree.getroot() + + gsettings_schema = "org.mate.terminal.profile" + terminal_settings = Gio.Settings.new_with_path(gsettings_schema, "/org/mate/terminal/profiles/default/") + terminal_settings.delay() + + for child in root: + # if the key exists, the user has a custom value + if 'name' in child.attrib: + + gsettings_key = gsettings_id(child.attrib['name']) + + # boolean + if child.attrib["type"] == "bool": + if child.attrib["value"] == "true": + debug_message(gsettings_schema, gsettings_key, True) + terminal_settings.set_boolean(gsettings_key, True) + else: + debug_message(gsettings_schema, gsettings_key, False) + terminal_settings.set_boolean(gsettings_key, False) + + # int + elif child.attrib["type"] == "int": + debug_message(gsettings_schema, gsettings_key, int(child.attrib["value"])) + terminal_settings.set_int(gsettings_key, int(child.attrib["value"])) + + # string + elif child.attrib["type"] == "string": + + value = child[0].text + if value != None: + debug_message(gsettings_schema, gsettings_key, value) + terminal_settings.set_string(gsettings_key, value) + + else: + debug_message("Unknown type", child.attrib["type"]) + + # apply settings! + terminal_settings.apply() + +# success! +dialog = Gtk.MessageDialog (None, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.INFO, + Gtk.ButtonsType.OK, + "MATE 1.4 settings migration completed!") +dialog.run() +dialog.destroy() diff --git a/tools/mate-conf-import.desktop.in.in b/tools/mate-conf-import.desktop.in.in new file mode 100644 index 0000000..97800f1 --- /dev/null +++ b/tools/mate-conf-import.desktop.in.in @@ -0,0 +1,10 @@ +[Desktop Entry] +_Name=Migrate MATE 1.4 settings +_Comment=Tool to migrate MATE 1.4 settings to MATE 1.6 +Exec=mate-conf-import +Icon=mateconf-editor +Terminal=false +Type=Application +Categories=GTK;Settings;DesktopSettings; +OnlyShowIn=MATE; +StartupNotify=false |