summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am15
-rwxr-xr-xtools/mate-conf-import507
-rw-r--r--tools/mate-conf-import.desktop.in.in10
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