summaryrefslogtreecommitdiff
path: root/src/Profiles.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/Profiles.vala')
-rw-r--r--src/Profiles.vala303
1 files changed, 303 insertions, 0 deletions
diff --git a/src/Profiles.vala b/src/Profiles.vala
new file mode 100644
index 0000000..ec52800
--- /dev/null
+++ b/src/Profiles.vala
@@ -0,0 +1,303 @@
+/* Copyright 2019 Jens Georg.
+ *
+ * This software is licensed under the GNU LGPL (version 2.1 or later).
+ * See the COPYING file in this distribution.
+ */
+
+namespace Shotwell {
+ class Profile : Object {
+ public const string SYSTEM = "__shotwell_default_system";
+ public Profile(string name, string id, string data_dir, bool active) {
+ Object(name: name, id: id, data_dir: data_dir, active: active);
+ }
+ public string name {get; construct;}
+ public string id {get; construct;}
+ public string data_dir {get; construct;}
+ public bool active {get; construct;}
+ }
+
+ class ProfileManager : Object, GLib.ListModel {
+ // ListModel implementations
+ Type get_item_type() {
+ return typeof(Profile);
+ }
+
+ uint get_n_items() {
+ // All that is in the ini file plus one for the default profile
+ return profiles.get_groups().length + 1;
+ }
+
+ GLib.Object? get_item (uint position) {
+ if (position == 0) {
+ return new Profile(_("System Profile"), Profile.SYSTEM,
+ Path.build_path(Path.DIR_SEPARATOR_S, Environment.get_user_data_dir(), "shotwell"),
+ this.profile == null);
+ }
+
+ try {
+ var group = profiles.get_groups()[position - 1];
+ var id = profiles.get_value(group, "Id");
+ var name = profiles.get_value(group, "Name");
+ var active = this.profile == name;
+ return new Profile(profiles.get_value(group, "Name"),
+ id,
+ get_data_dir_for_profile(id, group),
+ active);
+ } catch (KeyFileError err) {
+ if (err is KeyFileError.GROUP_NOT_FOUND) {
+ assert_not_reached();
+ }
+
+ warning("Profile configuration file corrupt: %s", err.message);
+ }
+
+ return null;
+ }
+
+ private static ProfileManager instance;
+ public static ProfileManager get_instance() {
+ if (instance == null)
+ instance = new ProfileManager();
+
+ return instance;
+ }
+
+ private ProfileManager() {
+ Object();
+ }
+
+ private void write() {
+ try {
+ profiles.save_to_file(path);
+ } catch (Error error) {
+ critical("Failed to write profiles: %s", error.message);
+ }
+ }
+
+ private KeyFile profiles;
+ private string profile = null;
+ private string path;
+ private string group_name;
+
+ public override void constructed() {
+ base.constructed();
+
+ profiles = new KeyFile();
+ path = Path.build_filename(Environment.get_user_config_dir(), "shotwell");
+ DirUtils.create_with_parents(path, 0700);
+ path = Path.build_filename(path, "profiles.ini");
+
+ try {
+ profiles.load_from_file(path, KeyFileFlags.KEEP_COMMENTS);
+ } catch (Error error) {
+ debug("Could not read profiles: %s", error.message);
+ }
+ }
+
+ public bool has_profile (string profile, out string group_name = null) {
+ group_name = Base64.encode (profile.data);
+ return profiles.has_group(group_name);
+ }
+
+ public void set_profile(string profile) {
+ message("Using profile %s for this session", profile);
+ assert(this.profile == null);
+
+ this.profile = profile;
+
+ add_profile(Uuid.string_random(), profile, null, null);
+ }
+
+ public void add_profile(string id, string name, string? library_folder, string? data_folder) {
+ if (has_profile(name, out this.group_name)) {
+ return;
+ }
+
+ try {
+ profiles.set_string(group_name, "Name", name);
+ profiles.set_string(group_name, "Id", id);
+ if (data_folder != null) {
+ profiles.set_string(group_name, "DataDir", data_folder);
+ }
+
+ // Need to set comment after setting keys since it does not create the group
+ profiles.set_comment(group_name, null, "Profile settings for \"%s\"".printf(name));
+
+ write();
+ } catch (Error err) {
+ error("Failed to create profile: %s", err.message);
+ }
+
+ if (library_folder != null) {
+ errno = 0;
+ var f = File.new_for_commandline_arg(library_folder);
+ try {
+ f.make_directory_with_parents();
+ } catch (Error err) {
+ warning ("Failed to create library folder: %s", err.message);
+ }
+ var settings_path = "/org/gnome/shotwell/profiles/" + id + "/preferences/files/";
+
+
+ var settings = new Settings.with_path("org.gnome.shotwell.preferences.files", settings_path);
+ settings.set_string("import-dir", library_folder);
+ }
+
+ items_changed(profiles.get_groups().length, 0, 1);
+ }
+
+ public string derive_data_dir(string? data_dir) {
+ if (data_dir != null) {
+ debug ("Using user-provided data dir %s", data_dir);
+
+ try {
+ profiles.get_string(group_name, "DataDir");
+ } catch (Error error) {
+ if (profile != null && profile != "") {
+ profiles.set_string(group_name ,"DataDir", data_dir);
+ debug("Using %s as data dir for profile %s", data_dir, profile);
+ write();
+ }
+ }
+
+ return data_dir;
+ }
+
+ return Path.build_filename(Environment.get_user_data_dir(), "shotwell", "profiles", id());
+ }
+
+ public string id() {
+ // We are not running on any profile
+ if (profile == null || profile == "")
+ return "";
+
+ try {
+ return profiles.get_string(group_name, "Id");
+ } catch (Error error) {
+ assert_not_reached();
+ }
+ }
+
+ private string get_data_dir_for_profile(string id, string group) throws KeyFileError {
+ if ("DataDir" in profiles.get_keys(group)) {
+ return profiles.get_value(group, "DataDir");
+ } else {
+ return Path.build_filename(Environment.get_user_data_dir(), "shotwell", "profiles", id);
+ }
+ }
+
+ public void print_profiles() {
+ print("Available profiles:\n");
+ print("-------------------\n");
+ try {
+ foreach (var group in profiles.get_groups()) {
+ print("Profile name: %s\n", profiles.get_value(group, "Name"));
+ var id = profiles.get_value(group, "Id");
+ print("Profile Id: %s\n", id);
+ print("Data dir: %s\n", get_data_dir_for_profile(id, group));
+ print("\n");
+ }
+ } catch (Error error) {
+ print("Failed to print profiles: %s", error.message);
+ }
+ }
+
+ const string SCHEMAS[] = {
+ "sharing",
+ "printing",
+ "plugins.enable-state",
+ "preferences.ui",
+ "preferences.slideshow",
+ "preferences.window",
+ "preferences.files",
+ "preferences.editing",
+ "preferences.export",
+ };
+
+ void reset_all_keys(Settings settings) {
+ SettingsSchema schema;
+ ((Object)settings).get("settings-schema", out schema, null);
+
+ foreach (var key in schema.list_keys()) {
+ debug("Resetting key %s", key);
+ settings.reset(key);
+ }
+
+ foreach (var c in settings.list_children()) {
+ debug("Checking children %s", c);
+ var child = settings.get_child (c);
+ reset_all_keys (child);
+ }
+ }
+
+ private void remove_settings_recursively(string id) {
+ var source = SettingsSchemaSource.get_default();
+ foreach (var schema in SCHEMAS) {
+ var path = "/org/gnome/shotwell/profiles/%s/%s/".printf(id, schema.replace(".", "/"));
+ var schema_name = "org.gnome.shotwell.%s".printf(schema);
+ debug("%s @ %s", schema_name, path);
+ var schema_definition = source.lookup(schema_name, false);
+ var settings = new Settings.full (schema_definition, null, path);
+ settings.delay();
+ reset_all_keys (settings);
+ foreach (var key in schema_definition.list_keys()) {
+ debug("Resetting key %s", key);
+ settings.reset(key);
+ }
+ settings.apply();
+ Settings.sync();
+ }
+ }
+
+ public void remove(string id, bool remove_all) {
+ debug("Request to remove profile %s, with files? %s", id, remove_all.to_string());
+ int index = 1;
+ string group = null;
+
+ foreach (var g in profiles.get_groups()) {
+ try {
+ if (profiles.get_value(g, "Id") == id) {
+ group = g;
+ break;
+ }
+ index++;
+ } catch (KeyFileError error) {
+ assert_not_reached();
+ }
+ }
+
+ if (group != null) {
+ string? data_dir = null;
+
+ try {
+ data_dir = get_data_dir_for_profile(id, group);
+ // Remove profile
+ string? key = null;
+ profiles.remove_comment(group, key);
+ profiles.remove_group(group);
+ } catch (KeyFileError err) {
+ // We checked the existence of the group above.
+ assert_not_reached();
+ }
+
+ remove_settings_recursively(id);
+
+ if (remove_all) {
+ try {
+ var file = File.new_for_commandline_arg(data_dir);
+ file.trash();
+ } catch (Error error) {
+ warning("Failed to remove data folder: %s", error.message);
+ }
+ }
+
+ Idle.add(() => {
+ items_changed(index, 1, 0);
+
+ return false;
+ });
+ write();
+ }
+ }
+ }
+}