/*
 *  Entangle: Tethered Camera Control & Capture
 *
 *  Copyright (C) 2009-2018 Daniel P. Berrangé
 *
 *  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/>.
 *
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <glib.h>

#include "entangle-preferences.h"

#include "entangle-debug.h"
#include "entangle-progress.h"

struct _EntanglePreferences
{
    GObject parent;

    GSettings *interfaceSettings;
    GSettings *captureSettings;
    GSettings *cmsSettings;
    GSettings *imgSettings;
};

G_DEFINE_TYPE(EntanglePreferences, entangle_preferences, G_TYPE_OBJECT);

#define SETTING_INTERFACE "interface"
#define SETTING_CAPTURE "capture"
#define SETTING_CMS "cms"
#define SETTING_IMG "img"

#define SETTING_INTERFACE_AUTO_CONNECT "auto-connect"
#define SETTING_INTERFACE_SCREEN_BLANK "screen-blank"
#define SETTING_INTERFACE_PLUGINS "plugins"
#define SETTING_INTERFACE_HISTOGRAM_LINEAR "histogram-linear"

#define SETTING_CAPTURE_FILENAME_PATTERN "filename-pattern"
#define SETTING_CAPTURE_LAST_SESSION "last-session"
#define SETTING_CAPTURE_CONTINUOUS_PREVIEW "continuous-preview"
#define SETTING_CAPTURE_ELECTRONIC_SHUTTER "electronic-shutter"
#define SETTING_CAPTURE_DELETE_FILE "delete-file"
#define SETTING_CAPTURE_SYNC_CLOCK "sync-clock"

#define SETTING_CMS_ENABLED "enabled"
#define SETTING_CMS_DETECT_SYSTEM_PROFILE "detect-system-profile"
#define SETTING_CMS_RGB_PROFILE "rgb-profile"
#define SETTING_CMS_MONITOR_PROFILE "monitor-profile"
#define SETTING_CMS_RENDERING_INTENT "rendering-intent"

#define SETTING_IMG_ASPECT_RATIO "aspect-ratio"
#define SETTING_IMG_MASK_OPACITY "mask-opacity"
#define SETTING_IMG_MASK_ENABLED "mask-enabled"
#define SETTING_IMG_OVEREXPOSURE_HIGHLIGHTING "overexposure-highlighting"
#define SETTING_IMG_FLIP_VERTICALLY "flip-vertically"
#define SETTING_IMG_FLIP_HORIZONTALLY "flip-horizontally"
#define SETTING_IMG_FOCUS_POINT "focus-point"
#define SETTING_IMG_GRID_LINES "grid-lines"
#define SETTING_IMG_EMBEDDED_PREVIEW "embedded-preview"
#define SETTING_IMG_ONION_SKIN "onion-skin"
#define SETTING_IMG_ONION_LAYERS "onion-layers"
#define SETTING_IMG_BACKGROUND "background"
#define SETTING_IMG_HIGHLIGHT "highlight"

#define PROP_NAME_INTERFACE_AUTO_CONNECT                                       \
    SETTING_INTERFACE "-" SETTING_INTERFACE_AUTO_CONNECT
#define PROP_NAME_INTERFACE_SCREEN_BLANK                                       \
    SETTING_INTERFACE "-" SETTING_INTERFACE_SCREEN_BLANK
#define PROP_NAME_INTERFACE_HISTOGRAM_LINEAR                                   \
    SETTING_INTERFACE "-" SETTING_INTERFACE_HISTOGRAM_LINEAR

#define PROP_NAME_CAPTURE_FILENAME_PATTERN                                     \
    SETTING_CAPTURE "-" SETTING_CAPTURE_FILENAME_PATTERN
#define PROP_NAME_CAPTURE_LAST_SESSION                                         \
    SETTING_CAPTURE "-" SETTING_CAPTURE_LAST_SESSION
#define PROP_NAME_CAPTURE_CONTINUOUS_PREVIEW                                   \
    SETTING_CAPTURE "-" SETTING_CAPTURE_CONTINUOUS_PREVIEW
#define PROP_NAME_CAPTURE_ELECTRONIC_SHUTTER                                   \
    SETTING_CAPTURE "-" SETTING_CAPTURE_ELECTRONIC_SHUTTER
#define PROP_NAME_CAPTURE_DELETE_FILE                                          \
    SETTING_CAPTURE "-" SETTING_CAPTURE_DELETE_FILE
#define PROP_NAME_CAPTURE_SYNC_CLOCK                                           \
    SETTING_CAPTURE "-" SETTING_CAPTURE_SYNC_CLOCK

#define PROP_NAME_CMS_ENABLED SETTING_CMS "-" SETTING_CMS_ENABLED
#define PROP_NAME_CMS_DETECT_SYSTEM_PROFILE                                    \
    SETTING_CMS "-" SETTING_CMS_DETECT_SYSTEM_PROFILE
#define PROP_NAME_CMS_RGB_PROFILE SETTING_CMS "-" SETTING_CMS_RGB_PROFILE
#define PROP_NAME_CMS_MONITOR_PROFILE                                          \
    SETTING_CMS "-" SETTING_CMS_MONITOR_PROFILE
#define PROP_NAME_CMS_RENDERING_INTENT                                         \
    SETTING_CMS "-" SETTING_CMS_RENDERING_INTENT

#define PROP_NAME_IMG_ASPECT_RATIO SETTING_IMG "-" SETTING_IMG_ASPECT_RATIO
#define PROP_NAME_IMG_MASK_OPACITY SETTING_IMG "-" SETTING_IMG_MASK_OPACITY
#define PROP_NAME_IMG_MASK_ENABLED SETTING_IMG "-" SETTING_IMG_MASK_ENABLED
#define PROP_NAME_IMG_OVEREXPOSURE_HIGHLIGHTING                                \
    SETTING_IMG "-" SETTING_IMG_OVEREXPOSURE_HIGHLIGHTING
#define PROP_NAME_IMG_FLIP_VERTICALLY                                          \
    SETTING_IMG "-" SETTING_IMG_FLIP_VERTICALLY
#define PROP_NAME_IMG_FLIP_HORIZONTALLY                                        \
    SETTING_IMG "-" SETTING_IMG_FLIP_HORIZONTALLY
#define PROP_NAME_IMG_FOCUS_POINT SETTING_IMG "-" SETTING_IMG_FOCUS_POINT
#define PROP_NAME_IMG_GRID_LINES SETTING_IMG "-" SETTING_IMG_GRID_LINES
#define PROP_NAME_IMG_EMBEDDED_PREVIEW                                         \
    SETTING_IMG "-" SETTING_IMG_EMBEDDED_PREVIEW
#define PROP_NAME_IMG_ONION_LAYERS SETTING_IMG "-" SETTING_IMG_ONION_LAYERS
#define PROP_NAME_IMG_ONION_SKIN SETTING_IMG "-" SETTING_IMG_ONION_SKIN
#define PROP_NAME_IMG_BACKGROUND SETTING_IMG "-" SETTING_IMG_BACKGROUND
#define PROP_NAME_IMG_HIGHLIGHT SETTING_IMG "-" SETTING_IMG_HIGHLIGHT

enum
{
    PROP_0,

    PROP_INTERFACE_AUTO_CONNECT,
    PROP_INTERFACE_SCREEN_BLANK,
    PROP_INTERFACE_HISTOGRAM_LINEAR,

    PROP_CAPTURE_FILENAME_PATTERN,
    PROP_CAPTURE_LAST_SESSION,
    PROP_CAPTURE_CONTINUOUS_PREVIEW,
    PROP_CAPTURE_ELECTRONIC_SHUTTER,
    PROP_CAPTURE_DELETE_FILE,
    PROP_CAPTURE_SYNC_CLOCK,

    PROP_CMS_ENABLED,
    PROP_CMS_RGB_PROFILE,
    PROP_CMS_MONITOR_PROFILE,
    PROP_CMS_DETECT_SYSTEM_PROFILE,
    PROP_CMS_RENDERING_INTENT,

    PROP_IMG_ASPECT_RATIO,
    PROP_IMG_MASK_OPACITY,
    PROP_IMG_MASK_ENABLED,
    PROP_IMG_OVEREXPOSURE_HIGHLIGHTING,
    PROP_IMG_FLIP_VERTICALLY,
    PROP_IMG_FLIP_HORIZONTALLY,
    PROP_IMG_FOCUS_POINT,
    PROP_IMG_GRID_LINES,
    PROP_IMG_EMBEDDED_PREVIEW,
    PROP_IMG_ONION_SKIN,
    PROP_IMG_ONION_LAYERS,
    PROP_IMG_BACKGROUND,
    PROP_IMG_HIGHLIGHT,
};

static char *
entangle_find_picture_dir(void)
{
    const gchar *baseDir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
    gchar *ret;

    if (!baseDir)
        baseDir = g_get_user_special_dir(
            G_USER_DIRECTORY_DESKTOP); // Guaranteed to be non-null

    ret = g_strdup_printf("%s/%s", baseDir, "Capture");
    ENTANGLE_DEBUG("******** PICTURE '%s'", ret);
    return ret;
}

static void
entangle_preferences_get_property(GObject *object,
                                  guint prop_id,
                                  GValue *value,
                                  GParamSpec *pspec)
{
    EntanglePreferences *prefs = ENTANGLE_PREFERENCES(object);
    EntangleColourProfile *prof;
    gchar *dir;
    gchar *file;
    gchar *val;

    switch (prop_id) {
    case PROP_INTERFACE_AUTO_CONNECT:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->interfaceSettings,
                                          SETTING_INTERFACE_AUTO_CONNECT));
        break;

    case PROP_INTERFACE_SCREEN_BLANK:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->interfaceSettings,
                                          SETTING_INTERFACE_SCREEN_BLANK));
        break;

    case PROP_INTERFACE_HISTOGRAM_LINEAR:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->interfaceSettings,
                                          SETTING_INTERFACE_HISTOGRAM_LINEAR));
        break;

    case PROP_CAPTURE_LAST_SESSION:
        dir = g_settings_get_string(prefs->captureSettings,
                                    SETTING_CAPTURE_LAST_SESSION);
        if (!dir)
            dir = entangle_find_picture_dir();
        g_value_set_string(value, dir);
        g_free(dir);
        break;

    case PROP_CAPTURE_FILENAME_PATTERN:
        file = g_settings_get_string(prefs->captureSettings,
                                     SETTING_CAPTURE_FILENAME_PATTERN);
        g_value_set_string(value, file);
        g_free(file);
        break;

    case PROP_CAPTURE_CONTINUOUS_PREVIEW:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->captureSettings,
                                          SETTING_CAPTURE_CONTINUOUS_PREVIEW));
        break;

    case PROP_CAPTURE_ELECTRONIC_SHUTTER:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->captureSettings,
                                          SETTING_CAPTURE_ELECTRONIC_SHUTTER));
        break;

    case PROP_CAPTURE_DELETE_FILE:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->captureSettings,
                                          SETTING_CAPTURE_DELETE_FILE));
        break;

    case PROP_CAPTURE_SYNC_CLOCK:
        g_value_set_boolean(value,
                            g_settings_get_boolean(prefs->captureSettings,
                                                   SETTING_CAPTURE_SYNC_CLOCK));
        break;

    case PROP_CMS_ENABLED:
        g_value_set_boolean(value, g_settings_get_boolean(prefs->cmsSettings,
                                                          SETTING_CMS_ENABLED));
        break;

    case PROP_CMS_RGB_PROFILE:
        file =
            g_settings_get_string(prefs->cmsSettings, SETTING_CMS_RGB_PROFILE);
        if (!file)
            file = g_strdup(PKGDATADIR "/sRGB.icc");
        prof = entangle_colour_profile_new_file(file);
        g_value_set_object(value, prof);
        g_object_unref(prof);
        g_free(file);
        break;

    case PROP_CMS_MONITOR_PROFILE:
        file = g_settings_get_string(prefs->cmsSettings,
                                     SETTING_CMS_MONITOR_PROFILE);
        if (file)
            prof = entangle_colour_profile_new_file(file);
        else
            prof = NULL;
        g_value_set_object(value, prof);
        g_object_unref(prof);
        g_free(file);
        break;

    case PROP_CMS_DETECT_SYSTEM_PROFILE:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->cmsSettings,
                                          SETTING_CMS_DETECT_SYSTEM_PROFILE));
        break;

    case PROP_CMS_RENDERING_INTENT:
        g_value_set_enum(value,
                         g_settings_get_enum(prefs->cmsSettings,
                                             SETTING_CMS_RENDERING_INTENT));
        break;

    case PROP_IMG_MASK_ENABLED:
        g_value_set_boolean(value,
                            g_settings_get_boolean(prefs->imgSettings,
                                                   SETTING_IMG_MASK_ENABLED));
        break;

    case PROP_IMG_OVEREXPOSURE_HIGHLIGHTING:
        g_value_set_boolean(value, g_settings_get_boolean(
                                       prefs->imgSettings,
                                       SETTING_IMG_OVEREXPOSURE_HIGHLIGHTING));
        break;

    case PROP_IMG_FLIP_VERTICALLY:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->imgSettings,
                                          SETTING_IMG_FLIP_VERTICALLY));
        break;

    case PROP_IMG_FLIP_HORIZONTALLY:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->imgSettings,
                                          SETTING_IMG_FLIP_HORIZONTALLY));
        break;

    case PROP_IMG_ASPECT_RATIO:
        val =
            g_settings_get_string(prefs->imgSettings, SETTING_IMG_ASPECT_RATIO);
        g_value_set_string(value, val);
        g_free(val);
        break;

    case PROP_IMG_MASK_OPACITY:
        g_value_set_int(value, g_settings_get_int(prefs->imgSettings,
                                                  SETTING_IMG_MASK_OPACITY));
        break;

    case PROP_IMG_FOCUS_POINT:
        g_value_set_boolean(value,
                            g_settings_get_boolean(prefs->imgSettings,
                                                   SETTING_IMG_FOCUS_POINT));
        break;

    case PROP_IMG_GRID_LINES:
        g_value_set_int(value, g_settings_get_enum(prefs->imgSettings,
                                                   SETTING_IMG_GRID_LINES));
        break;

    case PROP_IMG_EMBEDDED_PREVIEW:
        g_value_set_boolean(
            value, g_settings_get_boolean(prefs->imgSettings,
                                          SETTING_IMG_EMBEDDED_PREVIEW));
        break;

    case PROP_IMG_ONION_SKIN:
        g_value_set_boolean(
            value,
            g_settings_get_boolean(prefs->imgSettings, SETTING_IMG_ONION_SKIN));
        break;

    case PROP_IMG_ONION_LAYERS:
        g_value_set_int(value, g_settings_get_int(prefs->imgSettings,
                                                  SETTING_IMG_ONION_LAYERS));
        break;

    case PROP_IMG_BACKGROUND:
        val = g_settings_get_string(prefs->imgSettings, SETTING_IMG_BACKGROUND);
        g_value_set_string(value, val);
        g_free(val);
        break;

    case PROP_IMG_HIGHLIGHT:
        val = g_settings_get_string(prefs->imgSettings, SETTING_IMG_HIGHLIGHT);
        g_value_set_string(value, val);
        g_free(val);
        break;

    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    }
}

static void
entangle_preferences_set_property(GObject *object,
                                  guint prop_id,
                                  const GValue *value,
                                  GParamSpec *pspec)
{
    EntanglePreferences *prefs = ENTANGLE_PREFERENCES(object);
    EntangleColourProfile *prof;

    switch (prop_id) {
    case PROP_INTERFACE_AUTO_CONNECT:
        g_settings_set_boolean(prefs->interfaceSettings,
                               SETTING_INTERFACE_AUTO_CONNECT,
                               g_value_get_boolean(value));
        break;

    case PROP_INTERFACE_SCREEN_BLANK:
        g_settings_set_boolean(prefs->interfaceSettings,
                               SETTING_INTERFACE_SCREEN_BLANK,
                               g_value_get_boolean(value));
        break;

    case PROP_INTERFACE_HISTOGRAM_LINEAR:
        g_settings_set_boolean(prefs->interfaceSettings,
                               SETTING_INTERFACE_HISTOGRAM_LINEAR,
                               g_value_get_boolean(value));
        break;

    case PROP_CAPTURE_LAST_SESSION:
        g_settings_set_string(prefs->captureSettings,
                              SETTING_CAPTURE_LAST_SESSION,
                              g_value_get_string(value));
        break;

    case PROP_CAPTURE_FILENAME_PATTERN:
        g_settings_set_string(prefs->captureSettings,
                              SETTING_CAPTURE_FILENAME_PATTERN,
                              g_value_get_string(value));
        break;

    case PROP_CAPTURE_CONTINUOUS_PREVIEW:
        g_settings_set_boolean(prefs->captureSettings,
                               SETTING_CAPTURE_CONTINUOUS_PREVIEW,
                               g_value_get_boolean(value));
        break;

    case PROP_CAPTURE_ELECTRONIC_SHUTTER:
        g_settings_set_boolean(prefs->captureSettings,
                               SETTING_CAPTURE_ELECTRONIC_SHUTTER,
                               g_value_get_boolean(value));
        break;

    case PROP_CAPTURE_DELETE_FILE:
        g_settings_set_boolean(prefs->captureSettings,
                               SETTING_CAPTURE_DELETE_FILE,
                               g_value_get_boolean(value));
        break;

    case PROP_CAPTURE_SYNC_CLOCK:
        g_settings_set_boolean(prefs->captureSettings,
                               SETTING_CAPTURE_SYNC_CLOCK,
                               g_value_get_boolean(value));
        break;

    case PROP_CMS_ENABLED:
        g_settings_set_boolean(prefs->cmsSettings, SETTING_CMS_ENABLED,
                               g_value_get_boolean(value));
        break;

    case PROP_CMS_RGB_PROFILE:
        prof = g_value_get_object(value);
        if (prof)
            g_settings_set_string(prefs->cmsSettings, SETTING_CMS_RGB_PROFILE,
                                  entangle_colour_profile_filename(prof));
        else
            g_settings_set_string(prefs->cmsSettings, SETTING_CMS_RGB_PROFILE,
                                  NULL);
        break;

    case PROP_CMS_MONITOR_PROFILE:
        prof = g_value_get_object(value);
        if (prof)
            g_settings_set_string(prefs->cmsSettings,
                                  SETTING_CMS_MONITOR_PROFILE,
                                  entangle_colour_profile_filename(prof));
        else
            g_settings_set_string(prefs->cmsSettings,
                                  SETTING_CMS_MONITOR_PROFILE, NULL);
        break;

    case PROP_CMS_DETECT_SYSTEM_PROFILE:
        g_settings_set_boolean(prefs->cmsSettings,
                               SETTING_CMS_DETECT_SYSTEM_PROFILE,
                               g_value_get_boolean(value));
        break;

    case PROP_CMS_RENDERING_INTENT:
        g_settings_set_enum(prefs->cmsSettings, SETTING_CMS_RENDERING_INTENT,
                            g_value_get_enum(value));
        break;

    case PROP_IMG_MASK_ENABLED:
        g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_MASK_ENABLED,
                               g_value_get_boolean(value));
        break;

    case PROP_IMG_OVEREXPOSURE_HIGHLIGHTING:
        g_settings_set_boolean(prefs->imgSettings,
                               SETTING_IMG_OVEREXPOSURE_HIGHLIGHTING,
                               g_value_get_boolean(value));
        break;

    case PROP_IMG_FLIP_VERTICALLY:
        g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_FLIP_VERTICALLY,
                               g_value_get_boolean(value));
        break;

    case PROP_IMG_FLIP_HORIZONTALLY:
        g_settings_set_boolean(prefs->imgSettings,
                               SETTING_IMG_FLIP_HORIZONTALLY,
                               g_value_get_boolean(value));
        break;

    case PROP_IMG_ASPECT_RATIO:
        g_settings_set_string(prefs->imgSettings, SETTING_IMG_ASPECT_RATIO,
                              g_value_get_string(value));
        break;

    case PROP_IMG_MASK_OPACITY:
        g_settings_set_int(prefs->imgSettings, SETTING_IMG_MASK_OPACITY,
                           g_value_get_int(value));
        break;

    case PROP_IMG_FOCUS_POINT:
        g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_FOCUS_POINT,
                               g_value_get_boolean(value));
        break;

    case PROP_IMG_GRID_LINES:
        g_settings_set_enum(prefs->imgSettings, SETTING_IMG_GRID_LINES,
                            g_value_get_int(value));
        break;

    case PROP_IMG_EMBEDDED_PREVIEW:
        g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_EMBEDDED_PREVIEW,
                               g_value_get_boolean(value));
        break;

    case PROP_IMG_ONION_SKIN:
        g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_ONION_SKIN,
                               g_value_get_boolean(value));
        break;

    case PROP_IMG_ONION_LAYERS:
        g_settings_set_int(prefs->imgSettings, SETTING_IMG_ONION_LAYERS,
                           g_value_get_int(value));
        break;

    case PROP_IMG_BACKGROUND:
        g_settings_set_string(prefs->imgSettings, SETTING_IMG_BACKGROUND,
                              g_value_get_string(value));
        break;

    case PROP_IMG_HIGHLIGHT:
        g_settings_set_string(prefs->imgSettings, SETTING_IMG_HIGHLIGHT,
                              g_value_get_string(value));
        break;

    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    }
}

static void
entangle_preferences_finalize(GObject *object)
{
    EntanglePreferences *prefs = ENTANGLE_PREFERENCES(object);

    ENTANGLE_DEBUG("Finalize preferences %p", object);

    g_object_unref(prefs->interfaceSettings);
    g_object_unref(prefs->captureSettings);
    g_object_unref(prefs->cmsSettings);
    g_object_unref(prefs->imgSettings);

    G_OBJECT_CLASS(entangle_preferences_parent_class)->finalize(object);
}

static void
entangle_preferences_class_init(EntanglePreferencesClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS(klass);

    object_class->finalize = entangle_preferences_finalize;
    object_class->get_property = entangle_preferences_get_property;
    object_class->set_property = entangle_preferences_set_property;

    g_object_class_install_property(
        object_class, PROP_INTERFACE_AUTO_CONNECT,
        g_param_spec_boolean(PROP_NAME_INTERFACE_AUTO_CONNECT, "Auto connect",
                             "Automatically connect to cameras at startup",
                             TRUE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_INTERFACE_SCREEN_BLANK,
        g_param_spec_boolean(PROP_NAME_INTERFACE_SCREEN_BLANK, "Screen blank",
                             "Blank screen while capturing images", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_INTERFACE_HISTOGRAM_LINEAR,
        g_param_spec_boolean(PROP_NAME_INTERFACE_HISTOGRAM_LINEAR,
                             "Linear histogram", "Use linear histogram", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CAPTURE_LAST_SESSION,
        g_param_spec_string(PROP_NAME_CAPTURE_LAST_SESSION,
                            "Pictures directory",
                            "Directory to store pictures in", NULL,
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CAPTURE_FILENAME_PATTERN,
        g_param_spec_string(PROP_NAME_CAPTURE_FILENAME_PATTERN,
                            "Filename pattern",
                            "Pattern for creating new filenames", NULL,
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CAPTURE_DELETE_FILE,
        g_param_spec_boolean(PROP_NAME_CAPTURE_DELETE_FILE, "Delete file",
                             "Delete file after capturing", TRUE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CAPTURE_SYNC_CLOCK,
        g_param_spec_boolean(PROP_NAME_CAPTURE_SYNC_CLOCK, "Sync clock",
                             "Synchronize clock automatically", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CAPTURE_CONTINUOUS_PREVIEW,
        g_param_spec_boolean(PROP_NAME_CAPTURE_CONTINUOUS_PREVIEW,
                             "Continuous preview",
                             "Continue preview after capturing", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CAPTURE_ELECTRONIC_SHUTTER,
        g_param_spec_boolean(PROP_NAME_CAPTURE_ELECTRONIC_SHUTTER,
                             "Electronic shutter",
                             "Use preview output as capture image", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CMS_ENABLED,
        g_param_spec_boolean(PROP_NAME_CMS_ENABLED, "Colour managed display",
                             "Whether to enable colour management on display",
                             FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CMS_RGB_PROFILE,
        g_param_spec_object(PROP_NAME_CMS_RGB_PROFILE, "RGB Profile",
                            "Colour profile for workspace",
                            ENTANGLE_TYPE_COLOUR_PROFILE,
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CMS_MONITOR_PROFILE,
        g_param_spec_object(PROP_NAME_CMS_MONITOR_PROFILE, "Monitor profile",
                            "Colour profile for monitor",
                            ENTANGLE_TYPE_COLOUR_PROFILE,
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CMS_DETECT_SYSTEM_PROFILE,
        g_param_spec_boolean(PROP_NAME_CMS_DETECT_SYSTEM_PROFILE,
                             "Detect system profile",
                             "Detect the monitor colour profile", TRUE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CMS_RENDERING_INTENT,
        g_param_spec_enum(
            PROP_NAME_CMS_RENDERING_INTENT, "Profile rendering intent",
            "Rendering intent for images", ENTANGLE_TYPE_COLOUR_PROFILE_INTENT,
            ENTANGLE_COLOUR_PROFILE_INTENT_PERCEPTUAL,
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
                G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_ASPECT_RATIO,
        g_param_spec_string(PROP_NAME_IMG_ASPECT_RATIO, "Aspect ratio",
                            "Image mask aspect ratio", "1.33",
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_MASK_OPACITY,
        g_param_spec_int(PROP_NAME_IMG_MASK_OPACITY, "Mask opacity",
                         "Image mask border opacity", 0, 100, 90,
                         G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                             G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_MASK_ENABLED,
        g_param_spec_boolean(PROP_NAME_IMG_MASK_ENABLED, "Mask enabled",
                             "Enable aspect ratio image mask", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_OVEREXPOSURE_HIGHLIGHTING,
        g_param_spec_boolean(PROP_NAME_IMG_OVEREXPOSURE_HIGHLIGHTING,
                             "Overexposure highlighting",
                             "Highlight areas of overexposure", TRUE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_FLIP_VERTICALLY,
        g_param_spec_boolean(PROP_NAME_IMG_FLIP_VERTICALLY, "Flip vertically",
                             "Flip vertically", TRUE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_FLIP_HORIZONTALLY,
        g_param_spec_boolean(PROP_NAME_IMG_FLIP_HORIZONTALLY,
                             "Flip horizontally", "Flip horizontally", TRUE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_FOCUS_POINT,
        g_param_spec_boolean(PROP_NAME_IMG_FOCUS_POINT, "Focus point",
                             "Focus point during preview", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_GRID_LINES,
        g_param_spec_int(PROP_NAME_IMG_GRID_LINES, "Grid lines",
                         "Grid lines during preview", 0, 4, 4,
                         G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                             G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_EMBEDDED_PREVIEW,
        g_param_spec_boolean(PROP_NAME_IMG_EMBEDDED_PREVIEW, "Embedded preview",
                             "Embedded preview for raw files", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_ONION_LAYERS,
        g_param_spec_int(PROP_NAME_IMG_ONION_LAYERS, "Onion layer count",
                         "Overlay layers in image display", 1, 5, 3,
                         G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                             G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_ONION_SKIN,
        g_param_spec_boolean(PROP_NAME_IMG_ONION_SKIN, "Onion skin",
                             "Enable image overlay display", FALSE,
                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_BACKGROUND,
        g_param_spec_string(PROP_NAME_IMG_BACKGROUND, "Image background color",
                            "Image background color", "#000000",
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_IMG_HIGHLIGHT,
        g_param_spec_string(PROP_NAME_IMG_HIGHLIGHT, "Image highlight color",
                            "Image highlight color", "#FFFFFF",
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
                                G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
}

EntanglePreferences *
entangle_preferences_new(void)
{
    return ENTANGLE_PREFERENCES(g_object_new(ENTANGLE_TYPE_PREFERENCES, NULL));
}

void
entangle_preferences_ensure_gsettings_dir(void)
{
    const char *const *dirs;
    const char *dir;

    for (dirs = g_get_system_data_dirs(); *dirs; dirs++) {
        if (g_str_equal(*dirs, DATADIR)) {
            ENTANGLE_DEBUG("Found dir %s in system search dirs", *dirs);
            return;
        }
    }

    if ((dir = getenv("GSETTINGS_SCHEMA_DIR")) &&
        g_str_equal(dir, DATADIR "/glib-2.0/schemas")) {
        ENTANGLE_DEBUG("Found dir %s in GSETTINGS_SCHEMA_DIR", dir);
        return;
    }

    ENTANGLE_DEBUG("Setting %s in GSETTINGS_SCHEMA_DIR",
                   DATADIR "/glib-2.0/schemas");
    setenv("GSETTINGS_SCHEMA_DIR", DATADIR "/glib-2.0/schemas", 1);
}

void
entangle_preferences_ensure_girepository_dir(void)
{
#define GI_DIR LIBDIR "/girepository-1.0"
    const char *path;

    if (g_str_equal(PREFIX, "/usr")) {
        ENTANGLE_DEBUG("Installed into /usr, standard girepository location");
        return;
    }

    if ((path = getenv("GI_TYPELIB_PATH")) && strstr(path, GI_DIR)) {
        ENTANGLE_DEBUG("Found dir " GI_DIR " in GI_TYPELIB_PATH");
        return;
    }

    ENTANGLE_DEBUG("Setting %s in GSETTINGS_SCHEMA_DIR",
                   DATADIR "/glib-2.0/schemas");
    if (path) {
        char *dir = g_strdup_printf("%s:%s", path, GI_DIR);
        setenv("GI_TYPELIB_PATH", dir, 1);
        g_free(dir);
    } else {
        setenv("GI_TYPELIB_PATH", GI_DIR, 1);
    }
}

static void
entangle_preferences_init(EntanglePreferences *prefs)
{
    GSettings *settings = g_settings_new("org.entangle-photo.manager");
    prefs->interfaceSettings =
        g_settings_get_child(settings, SETTING_INTERFACE);
    prefs->captureSettings = g_settings_get_child(settings, SETTING_CAPTURE);
    prefs->cmsSettings = g_settings_get_child(settings, SETTING_CMS);
    prefs->imgSettings = g_settings_get_child(settings, SETTING_IMG);
    g_object_unref(settings);
}

/**
 * entangle_preferences_interface_get_auto_connect:
 * @prefs: (transfer none): the preferences store
 *
 * Determine whether the application will attempt to automatically
 * connect to cameras at startup
 *
 * Returns: TRUE if cameras will be automatically connected, FALSE otherwise
 */
gboolean
entangle_preferences_interface_get_auto_connect(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->interfaceSettings,
                                  SETTING_INTERFACE_AUTO_CONNECT);
}

/**
 * entangle_preferences_set_auto_connect:
 * @prefs: (transfer none): the preferences store
 * @autoconn: TRUE to turn on automatic connect of cameras
 *
 * If @autoconn is set to TRUE, the application will
 * attempt to automatically connect to cameras at startup
 */
void
entangle_preferences_interface_set_auto_connect(EntanglePreferences *prefs,
                                                gboolean autoconn)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->interfaceSettings,
                           SETTING_INTERFACE_AUTO_CONNECT, autoconn);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_INTERFACE_AUTO_CONNECT);
}

/**
 * entangle_preferences_interface_get_screen_blank:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the screen wil be blanked prior to capturing
 * the image
 *
 * Returns: TRUE if the screen will blank at time of capture
 */
gboolean
entangle_preferences_interface_get_screen_blank(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->interfaceSettings,
                                  SETTING_INTERFACE_SCREEN_BLANK);
}

/**
 * entangle_preferences_interface_set_screen_blank:
 * @prefs: (transfer none): the preferences store
 * @blank: TRUE to make the screen blank during capture
 *
 * If @blank is set to TRUE, the screen will be blanked
 * during capture to avoid light from the screen influencing
 * the scene being shot.
 */
void
entangle_preferences_interface_set_screen_blank(EntanglePreferences *prefs,
                                                gboolean blank)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->interfaceSettings,
                           SETTING_INTERFACE_SCREEN_BLANK, blank);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_INTERFACE_SCREEN_BLANK);
}

/**
 * entangle_preferences_interface_get_histogram_linear:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the histogram will be displayed in
 * linear or logarithmic mode
 *
 * Returns: TRUE if the histogram is linear, FALSE for logarithmic
 */
gboolean
entangle_preferences_interface_get_histogram_linear(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->interfaceSettings,
                                  SETTING_INTERFACE_HISTOGRAM_LINEAR);
}

/**
 * entangle_preferences_interface_set_histogram_linear:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to set the histogram to linear mode
 *
 * If @enabled is TRUE then the histogram will be displayed in
 * linear mode, otherwise logarithmic mode will be used
 */
void
entangle_preferences_interface_set_histogram_linear(EntanglePreferences *prefs,
                                                    gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->interfaceSettings,
                           SETTING_INTERFACE_HISTOGRAM_LINEAR, enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_INTERFACE_HISTOGRAM_LINEAR);
}

/**
 * entangle_preferences_interface_get_plugins:
 * @prefs: (transfer none): the preferences store
 *
 * Get the names of the plugins that are enabled for the
 * application
 *
 * Returns: (transfer full)(array zero-terminated=1): the list of plugin names,
 * NULL terminated
 */
gchar **
entangle_preferences_interface_get_plugins(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    return g_settings_get_strv(prefs->interfaceSettings,
                               SETTING_INTERFACE_PLUGINS);
}

/**
 * entangle_preferences_interface_add_plugin:
 * @prefs: (transfer none): the preferences store
 * @name: (transfer none): the plugin to add
 *
 * Add the plugin called @name to the active list
 */
void
entangle_preferences_interface_add_plugin(EntanglePreferences *prefs,
                                          const char *name)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    gchar **plugins = g_settings_get_strv(prefs->interfaceSettings,
                                          SETTING_INTERFACE_PLUGINS);
    gsize len = g_strv_length(plugins);
    gsize i;

    for (i = 0; i < len; i++)
        if (g_str_equal(name, plugins[i]))
            goto cleanup;

    plugins = g_renew(gchar *, plugins, len + 2);
    len++;
    plugins[len - 1] = g_strdup(name);
    plugins[len] = NULL;
    g_settings_set_strv(prefs->interfaceSettings, SETTING_INTERFACE_PLUGINS,
                        (const gchar *const *)plugins);

cleanup:
    g_strfreev(plugins);
}

/**
 * entangle_preferences_interface_remove_plugin:
 * @prefs: (transfer none): the preferences store
 * @name: (transfer none): the plugin to remove
 *
 * Remove the plugin called @name from the active list
 */
void
entangle_preferences_interface_remove_plugin(EntanglePreferences *prefs,
                                             const char *name)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    gchar **plugins = g_settings_get_strv(prefs->interfaceSettings,
                                          SETTING_INTERFACE_PLUGINS);
    gsize len = g_strv_length(plugins);
    gsize i, j;
    gchar **newplugins = g_new0(gchar *, len + 1);
    for (i = 0, j = 0; i < len; i++) {
        if (!g_str_equal(plugins[i], name)) {
            newplugins[j++] = plugins[i];
        } else {
            g_free(plugins[i]);
        }
        plugins[i] = NULL;
    }
    newplugins[j] = NULL;
    g_settings_set_strv(prefs->interfaceSettings, SETTING_INTERFACE_PLUGINS,
                        (const gchar *const *)newplugins);
    g_strfreev(newplugins);
    g_strfreev(plugins);
}

/**
 * entangle_preferences_capture_get_last_session:
 * @prefs: (transfer none): the preferences store
 *
 * Get the most recently used directory for the
 * image session
 *
 * Returns: (transfer full): the session directory
 */
char *
entangle_preferences_capture_get_last_session(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    char *dir = g_settings_get_string(prefs->captureSettings,
                                      SETTING_CAPTURE_LAST_SESSION);
    if (dir && (g_str_equal(dir, "") || !g_path_is_absolute(dir))) {
        g_free(dir);
        dir = NULL;
    }
    if (!dir)
        dir = entangle_find_picture_dir();
    return dir;
}

/**
 * entangle_preferences_capture_set_last_session:
 * @prefs: (transfer none): the preferences store
 * @dir: (transfer none): the new session
 *
 * Record @dir as being the most recently used session
 * directory
 */
void
entangle_preferences_capture_set_last_session(EntanglePreferences *prefs,
                                              const gchar *dir)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_string(prefs->captureSettings, SETTING_CAPTURE_LAST_SESSION,
                          dir);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CAPTURE_LAST_SESSION);
}

/**
 * entangle_preferences_capture_get_filename_pattern:
 * @prefs: (transfer none): the preferences store
 *
 * Get the filename pattern to use for naming images that
 * are saved after download. In the pattern any repeated
 * sequence of 'X' characters will be replaced with the
 * image sequence number
 *
 * Returns: (transfer full): the filename pattern.
 */
char *
entangle_preferences_capture_get_filename_pattern(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    return g_settings_get_string(prefs->captureSettings,
                                 SETTING_CAPTURE_FILENAME_PATTERN);
}

/**
 * entangle_preferences_capture_set_filename_pattern:
 * @prefs: (transfer none): the preferences store
 * @pattern: (transfer none): the filename pattern
 *
 * Set the pattern to use for naming images that are
 * saved after download.
 */
void
entangle_preferences_capture_set_filename_pattern(EntanglePreferences *prefs,
                                                  const gchar *pattern)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_string(prefs->captureSettings,
                          SETTING_CAPTURE_FILENAME_PATTERN, pattern);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CAPTURE_FILENAME_PATTERN);
}

/**
 * entangle_preferences_capture_get_continuous_preview:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the preview mode will continue to operate after each
 * image is captured.
 *
 * Returns: TRUE if preview mode will continue after capture, FALSE otherwise
 */
gboolean
entangle_preferences_capture_get_continuous_preview(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->captureSettings,
                                  SETTING_CAPTURE_CONTINUOUS_PREVIEW);
}

/**
 * entangle_preferences_capture_set_continuous_preview:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to make preview mode continue after capture
 *
 * If @enabled is set to TRUE, then the preview mode will
 * continue to run after each image is captured
 */
void
entangle_preferences_capture_set_continuous_preview(EntanglePreferences *prefs,
                                                    gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->captureSettings,
                           SETTING_CAPTURE_CONTINUOUS_PREVIEW, enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CAPTURE_CONTINUOUS_PREVIEW);
}

/**
 * entangle_preferences_capture_get_electronic_shutter:
 * @prefs: (transfer none): the preferences store
 *
 * Determines if the capture event will use the next preview output as
 * capture image, instead of triggering a normal capture, with shutter
 * mechanically moving.
 *
 * Returns: TRUE if no mechanical shutter action occurs on a capture, FALSE
 * otherwise
 */
gboolean
entangle_preferences_capture_get_electronic_shutter(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->captureSettings,
                                  SETTING_CAPTURE_ELECTRONIC_SHUTTER);
}

/**
 * entangle_preferences_capture_set_electronic_shutter:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE if no mechanical shutter action should occur on capture
 *
 * If @enabled is TRUE, then the camera shutter will not be activated
 * when capturing an image.
 */
void
entangle_preferences_capture_set_electronic_shutter(EntanglePreferences *prefs,
                                                    gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->captureSettings,
                           SETTING_CAPTURE_ELECTRONIC_SHUTTER, enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CAPTURE_ELECTRONIC_SHUTTER);
}

/**
 * entangle_preferences_capture_get_delete_file:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the file will be deleted from the camera after it
 * has been downloaded.
 *
 * Returns: TRUE if the files will be deleted after download
 */
gboolean
entangle_preferences_capture_get_delete_file(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->captureSettings,
                                  SETTING_CAPTURE_DELETE_FILE);
}

/**
 * entangle_preferences_capture_set_delete_file:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE if files should be deleted from camera after capture
 *
 * If @enabled is set to TRUE, then files will be deleted from the
 * camera after they are downloaded.
 */
void
entangle_preferences_capture_set_delete_file(EntanglePreferences *prefs,
                                             gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->captureSettings, SETTING_CAPTURE_DELETE_FILE,
                           enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CAPTURE_DELETE_FILE);
}

/**
 * entangle_preferences_capture_get_sync_clock:
 * @prefs: (transfer none): the preferences store
 *
 * Determines if the camera clock will be automatically synchronized
 * to the host computer clock when first connecting
 *
 * Returns: TRUE if the clock will synchronized, FALSE otherwise
 */
gboolean
entangle_preferences_capture_get_sync_clock(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->captureSettings,
                                  SETTING_CAPTURE_SYNC_CLOCK);
}

/**
 * entangle_preferences_capture_set_sync_clock:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE if the clock should be synchronized
 *
 * If @enabled is TRUE, then the camera clock will be synchronized to
 * the host computer clock when first connecting
 */
void
entangle_preferences_capture_set_sync_clock(EntanglePreferences *prefs,
                                            gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->captureSettings, SETTING_CAPTURE_SYNC_CLOCK,
                           enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CAPTURE_SYNC_CLOCK);
}

/**
 * entangle_preferences_cms_get_rgb_profile:
 * @prefs: (transfer none): the preferences store
 *
 * Get the colour profile that represents the RGB working space
 *
 * Returns: (transfer full): the colour space
 */
EntangleColourProfile *
entangle_preferences_cms_get_rgb_profile(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    EntangleColourProfile *prof;
    gchar *val =
        g_settings_get_string(prefs->cmsSettings, SETTING_CMS_RGB_PROFILE);
    prof = entangle_colour_profile_new_file(val);
    g_free(val);

    return prof;
}

/**
 * entangle_preferences_cms_set_rgb_profile:
 * @prefs: (transfer none): the preferences store
 * @prof: (transfer none)(allow-none): the new rgb profile
 *
 * Set the colour profile that represents the RGB working space
 */
void
entangle_preferences_cms_set_rgb_profile(EntanglePreferences *prefs,
                                         EntangleColourProfile *prof)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_string(prefs->cmsSettings, SETTING_CMS_RGB_PROFILE,
                          prof ? entangle_colour_profile_filename(prof) : NULL);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CMS_RGB_PROFILE);
}

/**
 * entangle_preferences_cms_get_monitor_profile:
 * @prefs: (transfer none): the preferences store
 *
 * Get the profile associated with the display, if any.
 *
 * Returns: (transfer full): the colour profile
 */
EntangleColourProfile *
entangle_preferences_cms_get_monitor_profile(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    EntangleColourProfile *prof;
    gchar *val =
        g_settings_get_string(prefs->cmsSettings, SETTING_CMS_MONITOR_PROFILE);
    prof = entangle_colour_profile_new_file(val);
    g_free(val);
    return prof;
}

/**
 * entangle_preferences_cms_set_monitor_profile:
 * @prefs: (transfer none): the preferences store
 * @prof: (transfer none)(allow-none): the new monitor profile
 *
 * If @prof is not NULL, it will be used as the current monitor
 * profile. This is only honoured if automatic detection of
 * the monitor profile is disabled.
 */
void
entangle_preferences_cms_set_monitor_profile(EntanglePreferences *prefs,
                                             EntangleColourProfile *prof)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_string(prefs->cmsSettings, SETTING_CMS_MONITOR_PROFILE,
                          prof ? entangle_colour_profile_filename(prof) : NULL);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CMS_MONITOR_PROFILE);
}

/**
 * entangle_preferences_cms_get_enabled:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if images should be displayed with colour management
 * applied
 *
 * Returns: TRUE if colour management is active
 */
gboolean
entangle_preferences_cms_get_enabled(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->cmsSettings, SETTING_CMS_ENABLED);
}

/**
 * entangle_preferences_cms_set_enabled:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to enable colour management
 *
 * If @enabled is TRUE, colour management will be applied when
 * displaying images
 */
void
entangle_preferences_cms_set_enabled(EntanglePreferences *prefs,
                                     gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->cmsSettings, SETTING_CMS_ENABLED, enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CMS_ENABLED);
}

/**
 * entangle_preferences_cms_get_detect_system_profile:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the monitor profile will be automatically
 * detected, which is usually preferrable since
 * it copes with multiple monitor scenarios
 */
gboolean
entangle_preferences_cms_get_detect_system_profile(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->cmsSettings,
                                  SETTING_CMS_DETECT_SYSTEM_PROFILE);
}

/**
 * entangle_preferences_cms_set_detect_system_profile:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to automatically detect the monitor profile
 *
 * If @enabled is TRUE then the monitor profile will be
 * automatically detected
 */
void
entangle_preferences_cms_set_detect_system_profile(EntanglePreferences *prefs,
                                                   gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->cmsSettings,
                           SETTING_CMS_DETECT_SYSTEM_PROFILE, enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CMS_DETECT_SYSTEM_PROFILE);
}

/**
 * entangle_preferences_cms_get_rendering_intent:
 * @prefs: (transfer none): the preferences store
 *
 * Determine the rendering intent for displaying images
 *
 * Returns: the image rendering intent
 */
EntangleColourProfileIntent
entangle_preferences_cms_get_rendering_intent(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), 0);

    return g_settings_get_enum(prefs->cmsSettings,
                               SETTING_CMS_RENDERING_INTENT);
}

/**
 * entangle_preferences_cms_set_rendering_intent:
 * @prefs: (transfer none): the preferences store
 * @intent: the new rendering intent
 *
 * Set the rendering intent for displaying images
 */
void
entangle_preferences_cms_set_rendering_intent(
    EntanglePreferences *prefs,
    EntangleColourProfileIntent intent)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_enum(prefs->cmsSettings, SETTING_CMS_RENDERING_INTENT,
                        intent);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_CMS_RENDERING_INTENT);
}

/**
 * entangle_preferences_img_get_aspect_ratio:
 * @prefs: (transfer none): the preferences store
 *
 * Get the aspect ratio for any mask to apply to the image
 *
 * Returns: (transfer full): the aspect ratio for the mask
 */
gchar *
entangle_preferences_img_get_aspect_ratio(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    return g_settings_get_string(prefs->imgSettings, SETTING_IMG_ASPECT_RATIO);
}

/**
 * entangle_preferences_img_set_aspect_ratio:
 * @prefs: (transfer none): the preferences store
 * @aspect: the new aspect ratio
 *
 * Set the aspect ratio for any mask to apply to the image
 */
void
entangle_preferences_img_set_aspect_ratio(EntanglePreferences *prefs,
                                          const gchar *aspect)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_string(prefs->imgSettings, SETTING_IMG_ASPECT_RATIO, aspect);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_ASPECT_RATIO);
}

/**
 * entangle_preferences_img_get_mask_opacity:
 * @prefs: (transfer none): the preferences store
 *
 * Get the opacity of any mask to apply to the image
 *
 * Returns: the opacity between 0 and 100
 */
gint
entangle_preferences_img_get_mask_opacity(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), 0);

    return g_settings_get_int(prefs->imgSettings, SETTING_IMG_MASK_OPACITY);
}

/**
 * entangle_preferences_img_set_mask_opacity:
 * @prefs: (transfer none): the preferences store
 * @opacity: the opacity of the mask between 0 and 100
 *
 * Set the opacity to use when rendering the image mask
 */
void
entangle_preferences_img_set_mask_opacity(EntanglePreferences *prefs,
                                          gint opacity)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_int(prefs->imgSettings, SETTING_IMG_MASK_OPACITY, opacity);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_MASK_OPACITY);
}

/**
 * entangle_preferences_img_get_mask_enabled:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if an aspect ratio mask to be applied to the
 * image display
 *
 * Returns: TRUE if an aspect ratio mask should be applied
 */
gboolean
entangle_preferences_img_get_mask_enabled(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->imgSettings, SETTING_IMG_MASK_ENABLED);
}

/**
 * entangle_preferences_img_set_mask_enabled:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to apply an aspect ratio mask
 *
 * If @enabled is TRUE an aspect ratio mask will be applied
 * to the image display
 */
void
entangle_preferences_img_set_mask_enabled(EntanglePreferences *prefs,
                                          gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_MASK_ENABLED,
                           enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_MASK_ENABLED);
}

/**
 * entangle_preferences_img_get_overexposure_highlighting:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if areas of overexposure should be highlighted on
 * the image display
 *
 * Returns: TRUE if overexposure should be highlighted
 */
gboolean
entangle_preferences_img_get_overexposure_highlighting(
    EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->imgSettings,
                                  SETTING_IMG_OVEREXPOSURE_HIGHLIGHTING);
}

/**
 * entangle_preferences_img_set_overexposure_highlighting:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to highlight overeposure
 *
 * If @enabled is TRUE areas of overexposure will be highlighted on
 * the image display
 */
void
entangle_preferences_img_set_overexposure_highlighting(
    EntanglePreferences *prefs,
    gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->imgSettings,
                           SETTING_IMG_OVEREXPOSURE_HIGHLIGHTING, enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_OVEREXPOSURE_HIGHLIGHTING);
}

/**
 * entangle_preferences_img_get_flip_vertically:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the image display should be flipped vertically
 *
 * Returns: TRUE if image display should be flipped vertically
 */
gboolean
entangle_preferences_img_get_flip_vertically(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->imgSettings,
                                  SETTING_IMG_FLIP_VERTICALLY);
}

/**
 * entangle_preferences_img_set_flip_vertically:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to flip vertically
 *
 * If @enabled is TRUE the image display will be flipped vertically
 */
void
entangle_preferences_img_set_flip_vertically(EntanglePreferences *prefs,
                                             gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_FLIP_VERTICALLY,
                           enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_FLIP_VERTICALLY);
}

/**
 * entangle_preferences_img_get_flip_horizontally:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the image display should be flipped horizontally
 *
 * Returns: TRUE if image display should be flipped horizontally
 */
gboolean
entangle_preferences_img_get_flip_horizontally(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->imgSettings,
                                  SETTING_IMG_FLIP_HORIZONTALLY);
}

/**
 * entangle_preferences_img_set_flip_horizontally:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to flip horizontally
 *
 * If @enabled is TRUE the image display will be flipped horizontally
 */
void
entangle_preferences_img_set_flip_horizontally(EntanglePreferences *prefs,
                                               gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_FLIP_HORIZONTALLY,
                           enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_FLIP_HORIZONTALLY);
}

/**
 * entangle_preferences_img_get_focus_point:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if the center focus point should be displayed in
 * preview mode
 *
 * Returns: TRUE if a focus point is to be rendered
 */
gboolean
entangle_preferences_img_get_focus_point(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->imgSettings, SETTING_IMG_FOCUS_POINT);
}

/**
 * entangle_preferences_img_set_focus_point:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to render a focus point
 *
 * If @enabled is TRUE then a focus point will be display in
 * preview mode.
 */
void
entangle_preferences_img_set_focus_point(EntanglePreferences *prefs,
                                         gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_FOCUS_POINT,
                           enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_FOCUS_POINT);
}

/**
 * entangle_preferences_img_get_grid_lines:
 * @prefs: (transfer none): the preferences store
 *
 * Determine what grid lines to display in preview mode
 *
 * Returns: the grid lines to display
 */
gint
entangle_preferences_img_get_grid_lines(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), 0);

    return g_settings_get_enum(prefs->imgSettings, SETTING_IMG_GRID_LINES);
}

/**
 * entangle_preferences_img_set_grid_lines:
 * @prefs: (transfer none): the preferences store
 * @gridLines: the grid lines to display
 *
 * Set the grid lines to display when in image preview mode
 */
void
entangle_preferences_img_set_grid_lines(EntanglePreferences *prefs,
                                        gint gridLines)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_enum(prefs->imgSettings, SETTING_IMG_GRID_LINES, gridLines);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_GRID_LINES);
}

/**
 * entangle_preferences_img_get_embedded_preview:
 * @prefs: (transfer none): the preferences store
 *
 * Determine whether to use the embedded preview from files
 * for thumbnails.
 *
 * Returns: TRUE if embedded preview should be used
 */
gboolean
entangle_preferences_img_get_embedded_preview(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->imgSettings,
                                  SETTING_IMG_EMBEDDED_PREVIEW);
}

/**
 * entangle_preferences_img_set_embedded_preview:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to use the embedded preview
 *
 * If @enabled is TRUE, any embedded preview will be used
 * when generating thumbnails rather than loading the full
 * resolution image
 */
void
entangle_preferences_img_set_embedded_preview(EntanglePreferences *prefs,
                                              gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_EMBEDDED_PREVIEW,
                           enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_EMBEDDED_PREVIEW);
}

/**
 * entangle_preferences_img_get_onion_layers:
 * @prefs: (transfer none): the preferences store
 *
 * Determine how many images to overlay in onion skinning mode
 *
 * Returns: the number of image overlays
 */
gint
entangle_preferences_img_get_onion_layers(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), 0);

    return g_settings_get_int(prefs->imgSettings, SETTING_IMG_ONION_LAYERS);
}

/**
 * entangle_preferences_img_set_onion_layers:
 * @prefs: (transfer none): the preferences store
 * @layers: the number of image overlays
 *
 * Set the number of images to overlay when in onion skinning
 * mode
 */
void
entangle_preferences_img_set_onion_layers(EntanglePreferences *prefs,
                                          gint layers)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_int(prefs->imgSettings, SETTING_IMG_ONION_LAYERS, layers);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_ONION_LAYERS);
}

/**
 * entangle_preferences_img_get_onion_skin:
 * @prefs: (transfer none): the preferences store
 *
 * Determine if onion skinning should be used when displaying
 * images
 *
 * Returns: TRUE if onion skinning is enabled
 */
gboolean
entangle_preferences_img_get_onion_skin(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), FALSE);

    return g_settings_get_boolean(prefs->imgSettings, SETTING_IMG_ONION_SKIN);
}

/**
 * entangle_preferences_img_set_onion_skin:
 * @prefs: (transfer none): the preferences store
 * @enabled: TRUE to enable onion skinning
 *
 * If @enabled is TRUE then onion skinning will be enabled
 * when displaying images
 */
void
entangle_preferences_img_set_onion_skin(EntanglePreferences *prefs,
                                        gboolean enabled)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_boolean(prefs->imgSettings, SETTING_IMG_ONION_SKIN, enabled);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_ONION_SKIN);
}

/**
 * entangle_preferences_img_get_background:
 * @prefs: (transfer none): the preferences store
 *
 * Get the colour used as the background when displaying images
 *
 * Returns: (transfer full): the background colour
 */
gchar *
entangle_preferences_img_get_background(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    return g_settings_get_string(prefs->imgSettings, SETTING_IMG_BACKGROUND);
}

/**
 * entangle_preferences_img_set_background:
 * @prefs: (transfer none): the preferences store
 * @bkg: (transfer none): the background colour
 *
 * Set the colour used as the background when displaying images
 */
void
entangle_preferences_img_set_background(EntanglePreferences *prefs,
                                        const gchar *bkg)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_string(prefs->imgSettings, SETTING_IMG_BACKGROUND, bkg);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_BACKGROUND);
}

/**
 * entangle_preferences_img_get_highlight:
 * @prefs: (transfer none): the preferences store
 *
 * Get the colour to use when highlighting images
 *
 * Returns: (transfer full): the highlight colour
 */
gchar *
entangle_preferences_img_get_highlight(EntanglePreferences *prefs)
{
    g_return_val_if_fail(ENTANGLE_IS_PREFERENCES(prefs), NULL);

    return g_settings_get_string(prefs->imgSettings, SETTING_IMG_HIGHLIGHT);
}

/**
 * entangle_preferences_img_set_highlight:
 * @prefs: (transfer none): the preferences store
 * @bkg: (transfer none): the highlight colour
 *
 * Set the colour to use when highlighting images
 */
void
entangle_preferences_img_set_highlight(EntanglePreferences *prefs,
                                       const gchar *bkg)
{
    g_return_if_fail(ENTANGLE_IS_PREFERENCES(prefs));

    g_settings_set_string(prefs->imgSettings, SETTING_IMG_HIGHLIGHT, bkg);
    g_object_notify(G_OBJECT(prefs), PROP_NAME_IMG_HIGHLIGHT);
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  indent-tabs-mode: nil
 *  tab-width: 8
 * End:
 */
