summaryrefslogtreecommitdiff
path: root/src/pies
diff options
context:
space:
mode:
authorAlessandro Ghedini <al3xbio@gmail.com>2011-10-19 10:56:04 +0200
committerAlessandro Ghedini <al3xbio@gmail.com>2011-10-19 10:56:04 +0200
commit6451a495637c6e3047a5a56573cffc6e3de9a515 (patch)
tree7c3eb29532e7c4b36a9da13c5890664fb816959b /src/pies
Imported Upstream version 0.2+gitdfdad95upstream/0.2+gitdfdad95
Diffstat (limited to 'src/pies')
-rw-r--r--src/pies/defaultConfig.vala70
-rw-r--r--src/pies/load.vala230
-rw-r--r--src/pies/pie.vala96
-rw-r--r--src/pies/pieManager.vala231
-rw-r--r--src/pies/save.vala81
5 files changed, 708 insertions, 0 deletions
diff --git a/src/pies/defaultConfig.vala b/src/pies/defaultConfig.vala
new file mode 100644
index 0000000..bd981b5
--- /dev/null
+++ b/src/pies/defaultConfig.vala
@@ -0,0 +1,70 @@
+/*
+Copyright (c) 2011 by Simon Schneegans
+
+This program 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.
+
+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 General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////
+/// A helper class which creates a user-specific default configuration.
+/////////////////////////////////////////////////////////////////////////
+
+namespace Pies {
+
+ public void create_default_config() {
+
+ // add a pie with playback controls
+ var multimedia = PieManager.create_persistent_pie(_("Multimedia"), "stock_media-play", "<Control><Alt>m");
+ multimedia.add_action(new KeyAction(_("Next Track"), "stock_media-next", "XF86AudioNext", true));
+ multimedia.add_action(new KeyAction(_("Stop"), "stock_media-stop", "XF86AudioStop"));
+ multimedia.add_action(new KeyAction(_("Previous Track"), "stock_media-prev", "XF86AudioPrev"));
+ multimedia.add_action(new KeyAction(_("Play/Pause"), "stock_media-play", "XF86AudioPlay"));
+
+ // add a pie with the users default applications
+ var apps = PieManager.create_persistent_pie(_("Applications"), "applications-accessories", "<Control><Alt>a");
+ apps.add_action(ActionRegistry.default_for_mime_type("text/plain"));
+ apps.add_action(ActionRegistry.default_for_mime_type("audio/ogg"));
+ apps.add_action(ActionRegistry.default_for_mime_type("video/ogg"));
+ apps.add_action(ActionRegistry.default_for_mime_type("image/jpg"));
+ apps.add_action(ActionRegistry.default_for_uri("http"));
+ apps.add_action(ActionRegistry.default_for_uri("mailto"));
+
+ // add a pie with the users bookmarks and devices
+ var bookmarks = PieManager.create_persistent_pie(_("Bookmarks"), "user-bookmarks", "<Control><Alt>b");
+ bookmarks.add_group(new BookmarkGroup(bookmarks.id));
+ bookmarks.add_group(new DevicesGroup(bookmarks.id));
+
+ // add a pie with session controls
+ var session = PieManager.create_persistent_pie(_("Session"), "gnome-session-halt", "<Control><Alt>q");
+ session.add_group(new SessionGroup(session.id));
+
+ // add a pie with a main menu
+ var menu = PieManager.create_persistent_pie(_("Main Menu"), "alacarte", "<Control><Alt>space");
+ menu.add_group(new MenuGroup(menu.id));
+
+ // add a pie with window controls
+ var window = PieManager.create_persistent_pie(_("Window"), "gnome-window-manager", "<Control><Alt>w");
+ window.add_action(new KeyAction(_("Scale"), "top", "<Control><Alt>s"));
+ window.add_action(new KeyAction(_("Minimize"), "bottom", "<Alt>F9", true));
+ window.add_action(new KeyAction(_("Close"), "window-close", "<Alt>F4"));
+ window.add_action(new KeyAction(_("Maximize"), "window_fullscreen", "<Alt>F10"));
+ window.add_action(new KeyAction(_("Restore"), "window_nofullscreen", "<Alt>F5"));
+
+ // save the configuration to file
+ Pies.save();
+ }
+}
+
+}
diff --git a/src/pies/load.vala b/src/pies/load.vala
new file mode 100644
index 0000000..912ddf0
--- /dev/null
+++ b/src/pies/load.vala
@@ -0,0 +1,230 @@
+/*
+Copyright (c) 2011 by Simon Schneegans
+
+This program 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.
+
+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 General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using GLib.Math;
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////
+/// A helper method which loads pies according to the configuration file.
+/////////////////////////////////////////////////////////////////////////
+
+namespace Pies {
+
+ /////////////////////////////////////////////////////////////////////
+ /// Loads all Pies from the pies.conf file.
+ /////////////////////////////////////////////////////////////////////
+
+ public void load() {
+ // check whether the config file exists
+ if (!GLib.File.new_for_path(Paths.pie_config).query_exists()) {
+ message("Creating new configuration file in \"" + Paths.pie_config + "\".");
+ Pies.create_default_config();
+ return;
+ }
+
+ // load the settings file
+ Xml.Parser.init();
+ Xml.Doc* piesXML = Xml.Parser.parse_file(Paths.pie_config);
+
+ if (piesXML != null) {
+ // begin parsing at the root element
+ Xml.Node* root = piesXML->get_root_element();
+ if (root != null) {
+ for (Xml.Node* node = root->children; node != null; node = node->next) {
+ if (node->type == Xml.ElementType.ELEMENT_NODE) {
+ string node_name = node->name.down();
+ switch (node_name) {
+ case "pie":
+ parse_pie(node);
+ break;
+ default:
+ warning("Invalid child element <" + node_name + "> in <pies> element pies.conf!");
+ break;
+ }
+ }
+ }
+ Xml.Parser.cleanup();
+
+ } else {
+ warning("Error loading pies: pies.conf is empty! The cake is a lie...");
+ }
+
+ delete piesXML;
+
+ } else {
+ warning("Error loading pies: pies.conf not found! The cake is a lie...");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Parses a <pie> element from the pies.conf file.
+ /////////////////////////////////////////////////////////////////////
+
+ private static void parse_pie(Xml.Node* node) {
+ string hotkey = "";
+ string name = "";
+ string icon = "";
+ string id = "";
+ int quick_action = -1;
+
+ // parse all attributes of this node
+ for (Xml.Attr* attribute = node->properties; attribute != null; attribute = attribute->next) {
+ string attr_name = attribute->name.down();
+ string attr_content = attribute->children->content;
+
+ switch (attr_name) {
+ case "hotkey":
+ hotkey = attr_content;
+ break;
+ case "quickaction":
+ quick_action = int.parse(attr_content);
+ break;
+ case "name":
+ name = attr_content;
+ break;
+ case "icon":
+ icon = attr_content;
+ break;
+ case "id":
+ id = attr_content;
+ break;
+ default:
+ warning("Invalid setting \"" + attr_name + "\" in pies.conf!");
+ break;
+ }
+ }
+
+ if (name == "") {
+ warning("Invalid <pie> element in pies.conf: No name specified!");
+ return;
+ }
+
+ // add a new Pie with the loaded properties
+ var pie = PieManager.create_persistent_pie(name, icon, hotkey, id);
+
+ // and parse all child elements
+ for (Xml.Node* slice = node->children; slice != null; slice = slice->next) {
+ if (slice->type == Xml.ElementType.ELEMENT_NODE) {
+ string node_name = slice->name.down();
+ switch (node_name) {
+ case "slice":
+ parse_slice(slice, pie);
+ break;
+ case "group":
+ parse_group(slice, pie);
+ break;
+ default:
+ warning("Invalid child element <" + node_name + "> in <pie> element in pies.conf!");
+ break;
+ }
+ }
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Parses a <slice> element from the pies.conf file.
+ /////////////////////////////////////////////////////////////////////
+
+ private static void parse_slice(Xml.Node* slice, Pie pie) {
+ string name="";
+ string icon="";
+ string command="";
+ string type="";
+ bool quick_action = false;
+
+ // parse all attributes of this node
+ for (Xml.Attr* attribute = slice->properties; attribute != null; attribute = attribute->next) {
+ string attr_name = attribute->name.down();
+ string attr_content = attribute->children->content;
+
+ switch (attr_name) {
+ case "name":
+ name = attr_content;
+ break;
+ case "icon":
+ icon = attr_content;
+ break;
+ case "command":
+ command = attr_content;
+ break;
+ case "type":
+ type = attr_content;
+ break;
+ case "quickaction":
+ quick_action = bool.parse(attr_content);
+ break;
+ default:
+ warning("Invalid attribute \"" + attr_name + "\" in <slice> element in pies.conf!");
+ break;
+ }
+ }
+
+ Action action = null;
+
+ // create a new Action according to the loaded type
+ foreach (var action_type in ActionRegistry.types) {
+ if (ActionRegistry.settings_names[action_type] == type) {
+
+ action = GLib.Object.new(action_type, "name", name,
+ "icon", icon,
+ "real_command", command,
+ "is_quick_action", quick_action) as Action;
+ break;
+ }
+ }
+
+ if (action != null) pie.add_action(action);
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Parses a <group> element from the pies.conf file.
+ /////////////////////////////////////////////////////////////////////
+
+ private static void parse_group(Xml.Node* slice, Pie pie) {
+ string type="";
+
+ // parse all attributes of this node
+ for (Xml.Attr* attribute = slice->properties; attribute != null; attribute = attribute->next) {
+ string attr_name = attribute->name.down();
+ string attr_content = attribute->children->content;
+
+ switch (attr_name) {
+ case "type":
+ type = attr_content;
+ break;
+ default:
+ warning("Invalid attribute \"" + attr_name + "\" in <group> element in pies.conf!");
+ break;
+ }
+ }
+
+ ActionGroup group = null;
+
+ // create a new ActionGroup according to the loaded type
+ foreach (var group_type in GroupRegistry.types) {
+ if (GroupRegistry.settings_names[group_type] == type) {
+ group = GLib.Object.new(group_type, "parent_id", pie.id) as ActionGroup;
+ break;
+ }
+ }
+
+ if (group != null) pie.add_group(group);
+ }
+}
+
+}
diff --git a/src/pies/pie.vala b/src/pies/pie.vala
new file mode 100644
index 0000000..0f87d8f
--- /dev/null
+++ b/src/pies/pie.vala
@@ -0,0 +1,96 @@
+/*
+Copyright (c) 2011 by Simon Schneegans
+
+This program 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.
+
+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 General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////
+/// This class stores information on a pie. A pie consists of a name, an
+/// icon name and an unique ID. Furthermore it has an arbitrary amount
+/// of ActionGroups storing Actions.
+/////////////////////////////////////////////////////////////////////////
+
+public class Pie : GLib.Object {
+
+ /////////////////////////////////////////////////////////////////////
+ /// The name of this Pie. It has not to be unique.
+ /////////////////////////////////////////////////////////////////////
+
+ public string name { get; construct; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// The name of the icon to be used for this Pie. It should exist in
+ /// the users current icon theme, else a standard icon will be used.
+ /////////////////////////////////////////////////////////////////////
+
+ public string icon { get; construct; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// The ID of this Pie. It has to be unique among all Pies. This ID
+ /// consists of three digits when the Pie was created by the user,
+ /// of four digits when it was created dynamically by another class,
+ /// for example by an ActionGroup.
+ /////////////////////////////////////////////////////////////////////
+
+ public string id { get; construct; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Stores all ActionGroups of this Pie.
+ /////////////////////////////////////////////////////////////////////
+
+ public Gee.ArrayList<ActionGroup?> action_groups { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// C'tor, initializes all given members.
+ /////////////////////////////////////////////////////////////////////
+
+ public Pie(string id, string name, string icon) {
+ GLib.Object(id: id, name: name, icon:icon);
+
+ this.action_groups = new Gee.ArrayList<ActionGroup?>();
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Should be called when this Pie is deleted, in order to clean up
+ /// stuff created by contained ActionGroups.
+ /////////////////////////////////////////////////////////////////////
+
+ public virtual void on_remove() {
+ foreach (var action_group in action_groups)
+ action_group.on_remove();
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Adds an Action to this Pie.
+ /////////////////////////////////////////////////////////////////////
+
+ public void add_action(Action action) {
+ var group = new ActionGroup(this.id);
+ group.add_action(action);
+ this.add_group(group);
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Adds an ActionGroup to this Pie.
+ /////////////////////////////////////////////////////////////////////
+
+ public void add_group(ActionGroup group) {
+ this.action_groups.add(group);
+ }
+}
+
+}
+
diff --git a/src/pies/pieManager.vala b/src/pies/pieManager.vala
new file mode 100644
index 0000000..eb031d0
--- /dev/null
+++ b/src/pies/pieManager.vala
@@ -0,0 +1,231 @@
+/*
+Copyright (c) 2011 by Simon Schneegans
+
+This program 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.
+
+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 General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////
+/// A static class which stores all Pies. It can be used to add, delete
+/// and open Pies.
+/////////////////////////////////////////////////////////////////////////
+
+public class PieManager : GLib.Object {
+
+ /////////////////////////////////////////////////////////////////////
+ /// A map of all Pies. It contains both, dynamic and persistent Pies.
+ /// They are associated to their ID's.
+ /////////////////////////////////////////////////////////////////////
+
+ public static Gee.HashMap<string, Pie?> all_pies { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Stores all global hotkeys.
+ /////////////////////////////////////////////////////////////////////
+
+ private static BindingManager bindings;
+
+ /////////////////////////////////////////////////////////////////////
+ /// True, if any pie has the current focus. If it is closing this
+ /// will be false already.
+ /////////////////////////////////////////////////////////////////////
+
+ private static bool a_pie_is_opened = false;
+
+ /////////////////////////////////////////////////////////////////////
+ /// Initializes all Pies. They are loaded from the pies.conf file.
+ /////////////////////////////////////////////////////////////////////
+
+ public static void init() {
+ all_pies = new Gee.HashMap<string, Pie?>();
+ bindings = new BindingManager();
+
+ // load all Pies from th pies.conf file
+ Pies.load();
+
+ // open the according pie if it's hotkey is pressed
+ bindings.on_press.connect((id) => {
+ open_pie(id);
+ });
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Opens the Pie with the given ID, if it exists.
+ /////////////////////////////////////////////////////////////////////
+
+ public static void open_pie(string id) {
+ if (!a_pie_is_opened) {
+ Pie? pie = all_pies[id];
+
+ if (pie != null) {
+ a_pie_is_opened = true;
+
+ var window = new PieWindow();
+ window.load_pie(pie);
+ window.open();
+
+ window.on_closing.connect(() => {
+ a_pie_is_opened = false;
+ });
+ } else {
+ warning("Failed to open pie with ID \"" + id + "\": ID does not exist!");
+ }
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Returns the hotkey which the Pie with the given ID is bound to.
+ /////////////////////////////////////////////////////////////////////
+
+ public static string get_accelerator_of(string id) {
+ return bindings.get_accelerator_of(id);
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Returns a human-readable version of the hotkey which the Pie
+ /// with the given ID is bound to.
+ /////////////////////////////////////////////////////////////////////
+
+ public static string get_accelerator_label_of(string id) {
+ return bindings.get_accelerator_label_of(id);
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Returns the name of the Pie with the given ID.
+ /////////////////////////////////////////////////////////////////////
+
+ public static string get_name_of(string id) {
+ Pie? pie = all_pies[id];
+ if (pie == null) return "";
+ else return pie.name;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Creates a new Pie which is displayed in the configuration dialog
+ /// and gets saved.
+ /////////////////////////////////////////////////////////////////////
+
+ public static Pie create_persistent_pie(string name, string icon_name, string hotkey, string? desired_id = null) {
+ Pie pie = create_pie(name, icon_name, 100, 999, desired_id);
+
+ if (hotkey != "") bindings.bind(hotkey, pie.id);
+
+ create_launcher(pie.id);
+
+ return pie;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Creates a new Pie which is not displayed in the configuration
+ /// dialog and is not saved.
+ /////////////////////////////////////////////////////////////////////
+
+ public static Pie create_dynamic_pie(string name, string icon_name, string? desired_id = null) {
+ return create_pie(name, icon_name, 1000, 9999, desired_id);
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Adds a new Pie. Can't be accesd from outer scope. Use
+ /// create_persistent_pie or create_dynamic_pie instead.
+ /////////////////////////////////////////////////////////////////////
+
+ private static Pie create_pie(string name, string icon_name, int min_id, int max_id, string? desired_id = null) {
+ var random = new GLib.Rand();
+
+ string final_id;
+
+ if (desired_id == null)
+ final_id = random.int_range(min_id, max_id).to_string();
+ else {
+ final_id = desired_id;
+ final_id.canon("0123456789", '_');
+ final_id = final_id.replace("_", "");
+
+ int id = int.parse(final_id);
+
+ if (id < min_id || id > max_id) {
+ final_id = random.int_range(min_id, max_id).to_string();
+ warning("The ID for pie \"" + name + "\" should be in range %u - %u! Using \"" + final_id + "\" instead of \"" + desired_id + "\"...", min_id, max_id);
+ }
+ }
+
+ if (all_pies.has_key(final_id)) {
+ var tmp = final_id;
+ var id_number = int.parse(final_id) + 1;
+ if (id_number == max_id+1) id_number = min_id;
+ final_id = id_number.to_string();
+ warning("Trying to add pie \"" + name + "\": ID \"" + tmp + "\" already exists! Using \"" + final_id + "\" instead...");
+ return create_pie(name, icon_name, min_id, max_id, final_id);
+ }
+
+ Pie pie = new Pie(final_id, name, icon_name);
+ all_pies.set(final_id, pie);
+
+ return pie;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Removes the Pie with the given ID if it exists. Additionally it
+ /// unbinds it's global hotkey.
+ /////////////////////////////////////////////////////////////////////
+
+ public static void remove_pie(string id) {
+ if (all_pies.has_key(id)) {
+ all_pies[id].on_remove();
+ all_pies.unset(id);
+ bindings.unbind(id);
+
+ if (id.length == 3)
+ remove_launcher(id);
+ }
+ else {
+ warning("Failed to remove pie with ID \"" + id + "\": ID does not exist!");
+ }
+ }
+
+ private static void create_launcher(string id) {
+ if (all_pies.has_key(id)) {
+ Pie? pie = all_pies[id];
+
+ string launcher_entry =
+ "#!/usr/bin/env xdg-open\n" +
+ "[Desktop Entry]\n" +
+ "Name=%s\n".printf(pie.name) +
+ "Exec=gnome-pie -o %s\n".printf(pie.id) +
+ "Encoding=UTF-8\n" +
+ "Type=Application\n" +
+ "Icon=%s\n".printf(pie.icon);
+
+ // create the launcher file
+ string launcher = Paths.launchers + "/%s.desktop".printf(pie.id);
+
+ try {
+ FileUtils.set_contents(launcher, launcher_entry);
+ FileUtils.chmod(launcher, 0755);
+ } catch (Error e) {
+ warning(e.message);
+ }
+ }
+ }
+
+ private static void remove_launcher(string id) {
+ string launcher = Paths.launchers + "/%s.desktop".printf(id);
+ if (FileUtils.test(launcher, FileTest.EXISTS)) {
+ FileUtils.remove(launcher);
+ }
+ }
+}
+
+}
diff --git a/src/pies/save.vala b/src/pies/save.vala
new file mode 100644
index 0000000..d691a95
--- /dev/null
+++ b/src/pies/save.vala
@@ -0,0 +1,81 @@
+/*
+Copyright (c) 2011 by Simon Schneegans
+
+This program 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.
+
+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 General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using GLib.Math;
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////
+/// A helper method which saves pies in a configuration file.
+/////////////////////////////////////////////////////////////////////////
+
+namespace Pies {
+
+ /////////////////////////////////////////////////////////////////////
+ /// Saves all Pies of the PieManager to the pies.conf file.
+ /////////////////////////////////////////////////////////////////////
+
+ public void save() {
+ // initializes the XML-Writer
+ var writer = new Xml.TextWriter.filename(Paths.pie_config);
+ writer.set_indent(true);
+ writer.start_document("1.0");
+ writer.start_element("pies");
+
+ // iterate through all Pies
+ foreach (var pie_entry in PieManager.all_pies.entries) {
+ var pie = pie_entry.value;
+
+ // if it's no dynamically created Pie
+ if (pie.id.length == 3) {
+ // write all attributes of the Pie
+ writer.start_element("pie");
+ writer.write_attribute("name", pie.name);
+ writer.write_attribute("id", pie.id);
+ writer.write_attribute("icon", pie.icon);
+ writer.write_attribute("hotkey", PieManager.get_accelerator_of(pie.id));
+
+ // and all of it's Actions
+ foreach (var group in pie.action_groups) {
+ // if it's a custom ActionGroup
+ if (group.get_type().depth() == 2) {
+ foreach (var action in group.actions) {
+ writer.start_element("slice");
+ writer.write_attribute("type", ActionRegistry.settings_names[action.get_type()]);
+ if (ActionRegistry.icon_name_editables[action.get_type()]) {
+ writer.write_attribute("name", action.name);
+ writer.write_attribute("icon", action.icon);
+ }
+ writer.write_attribute("command", action.real_command);
+ writer.write_attribute("quickAction", action.is_quick_action ? "true" : "false");
+ writer.end_element();
+ }
+ } else {
+ writer.start_element("group");
+ writer.write_attribute("type", GroupRegistry.settings_names[group.get_type()]);
+ writer.end_element();
+ }
+ }
+ writer.end_element();
+ }
+ }
+ writer.end_element();
+ writer.end_document();
+ }
+}
+
+}