[gnome-color-manager] Split gcm-prefs into a control center module and a profile viewer
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-color-manager] Split gcm-prefs into a control center module and a profile viewer
- Date: Fri, 25 Jun 2010 10:28:33 +0000 (UTC)
commit 89f0aff88775db164917b78b6f2b9422191ea4e6
Author: Richard Hughes <richard hughsie com>
Date: Fri Jun 25 11:03:45 2010 +0100
Split gcm-prefs into a control center module and a profile viewer
.gitignore | 3 +-
configure.ac | 6 +
contrib/gnome-color-manager.spec.in | 9 +-
data/Makefile.am | 1 +
data/figures/Makefile.am | 7 +-
data/gcm-prefs.desktop.in | 7 +-
data/gcm-prefs.ui | 1026 +---------
data/gcm-viewer.ui | 1108 +++++++++
data/org.gnome.color-manager.gschema.xml | 2 +
src/.gitignore | 2 +-
src/Makefile.am | 42 +-
src/cc-color-panel.c | 2931 ++++++++++++++++++++++++
src/cc-color-panel.h | 54 +
src/gcm-prefs.c | 3610 ------------------------------
src/gcm-viewer.c | 1173 ++++++++++
15 files changed, 5346 insertions(+), 4635 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 9fc437c..d77e9c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,7 @@ config.status
config.sub
configure
depcomp
-gnome-color-manager-*.tar.gz
+gnome-color-manager-*.tar.*
gtk-doc.make
install-sh
libtool
@@ -32,4 +32,3 @@ intltool-merge.in
intltool-update.in
.acb
*.patch
-
diff --git a/configure.ac b/configure.ac
index cc2b024..250f074 100644
--- a/configure.ac
+++ b/configure.ac
@@ -109,6 +109,12 @@ PKG_CHECK_MODULES(GUDEV, gudev-1.0)
PKG_CHECK_MODULES(LCMS, lcms2)
PKG_CHECK_MODULES(X11, x11)
+dnl Required for the properties window
+PKG_CHECK_MODULES(CONTROL_CENTER, [
+ libgnome-control-center >= 2.31.3])
+PANELS_DIR="${libdir}/control-center-1/panels"
+AC_SUBST(PANELS_DIR)
+
dnl **** Check for VTE ****
PKG_CHECK_MODULES(VTE, vte3 >= 0.25.1, has_vte=yes, has_vte=no)
AM_CONDITIONAL(HAVE_VTE, test x$has_vte = xyes)
diff --git a/contrib/gnome-color-manager.spec.in b/contrib/gnome-color-manager.spec.in
index 1d2ab3f..4d37922 100644
--- a/contrib/gnome-color-manager.spec.in
+++ b/contrib/gnome-color-manager.spec.in
@@ -62,6 +62,9 @@ for i in gcm-prefs gcm-import ; do
$RPM_BUILD_ROOT%{_datadir}/applications/$i.desktop
done
+rm -f $RPM_BUILD_ROOT%{_libdir}/control-center-1/panels/*.a
+rm -f $RPM_BUILD_ROOT%{_libdir}/control-center-1/panels/*.la
+
%find_lang %name --with-gnome
%post
@@ -92,8 +95,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &> /dev/null || :
%{_datadir}/gnome-color-manager/gcm-*.ui
%dir %{_datadir}/gnome-color-manager/targets
%dir %{_datadir}/gnome-color-manager/icons
-%{_datadir}/gnome-color-manager/targets/*.png
-%{_datadir}/gnome-color-manager/icons/*.svg
+%{_datadir}/gnome-color-manager/targets
+%{_datadir}/gnome-color-manager/icons
+%{_datadir}/gnome-color-manager/figures
%{_datadir}/man/man1/*.1.gz
%{_datadir}/gnome/help/gnome-color-manager
%{_datadir}/omf/gnome-color-manager
@@ -108,6 +112,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &> /dev/null || :
%{_datadir}/glib-2.0/schemas/org.gnome.color-manager.gschema.xml
%{_datadir}/GConf/gsettings/org.gnome.color-manager.gschema.migrate
%{_datadir}/dbus-1/interfaces/org.gnome.ColorManager.xml
+%{_libdir}/control-center-1/panels/*.so
%changelog
* #LONGDATE# Richard Hughes <richard hughsie com> #VERSION#-0.#BUILD##ALPHATAG#
diff --git a/data/Makefile.am b/data/Makefile.am
index 9de2564..fbd5f7b 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -33,6 +33,7 @@ pkgdata_DATA = \
gcm-calibrate.ui \
gcm-spawn.ui \
gcm-picker.ui \
+ gcm-viewer.ui \
gcm-prefs.ui
EXTRA_DIST = \
diff --git a/data/figures/Makefile.am b/data/figures/Makefile.am
index affc0c5..f662689 100644
--- a/data/figures/Makefile.am
+++ b/data/figures/Makefile.am
@@ -1,5 +1,9 @@
-figuresdir = $(datadir)/gnome-color-manager/icons
+figuresdir = $(datadir)/gnome-color-manager/figures
figures_DATA = \
+ viewer-example.png
+
+iconsdir = $(datadir)/gnome-color-manager/icons
+icons_DATA = \
clock.svg \
calibration-short.svg \
calibration-normal.svg \
@@ -18,5 +22,6 @@ figures_DATA = \
munki-screen.svg
EXTRA_DIST = \
+ $(icons_DATA) \
$(figures_DATA)
diff --git a/data/gcm-prefs.desktop.in b/data/gcm-prefs.desktop.in
index 56e11ee..edc6cfe 100644
--- a/data/gcm-prefs.desktop.in
+++ b/data/gcm-prefs.desktop.in
@@ -1,10 +1,10 @@
[Desktop Entry]
Encoding=UTF-8
-_Name=Color Profiles
-_GenericName=Color Profiles
+_Name=Color
+_GenericName=Color
_Comment=Manage ICC color profiles
Icon=gnome-color-manager
-Exec=gcm-prefs
+Exec=gnome-control-center color
Terminal=false
Type=Application
Categories=Settings;X-GNOME-SystemSettings;
@@ -12,3 +12,4 @@ StartupNotify=true
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-color-manager
X-GNOME-Bugzilla-Component=gnome-color-manager
+X-GNOME-Settings-Panel=color
diff --git a/data/gcm-prefs.ui b/data/gcm-prefs.ui
index 4f8b296..d86878f 100644
--- a/data/gcm-prefs.ui
+++ b/data/gcm-prefs.ui
@@ -702,978 +702,6 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox5">
- <property name="visible">True</property>
- <property name="border_width">9</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkVBox" id="vbox_profiles">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow2">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="treeview_profiles">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">False</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox45">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkButton" id="button_profile_import">
- <property name="label" translatable="yes">_Add…</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Add a new color profile</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button_profile_delete">
- <property name="label" translatable="yes">_Remove</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Delete this profile</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox_sections1">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">15</property>
- <child>
- <object class="GtkVBox" id="vbox13">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkVBox" id="vbox_profile_info">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkAlignment" id="alignment5">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkVBox" id="vbox_profiles_details">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">3</property>
- <child>
- <object class="GtkVBox" id="vbox_graph">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">3</property>
- <child>
- <object class="GtkHBox" id="hbox_graph">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox19">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_graph">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The graph representing the profile">Graph:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox38">
- <property name="visible">True</property>
- <child>
- <object class="GtkComboBox" id="combobox_graph">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_graph_widgets">
- <child>
- <object class="GtkHBox" id="hbox61">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_graph1">
- <property name="visible">True</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox60">
- <property name="visible">True</property>
- <child>
- <object class="GtkVBox" id="vbox_cie_axis">
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkHBox" id="hbox_cie_axis">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label17">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The CIE axis label, not to be confused with 'Y'">y</property>
- <property name="angle">90</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkAspectFrame" id="aspectframe_cie">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <property name="obey_child">False</property>
- <child>
- <object class="GtkHBox" id="hbox_cie_widget">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label18">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The CIE axis label, not to be confused with 'X'">x</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox_trc_axis">
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkHBox" id="hbox_trc_axis">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label7">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The TRC axis label">Response out</property>
- <property name="angle">90</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkAspectFrame" id="aspectframe_trc">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <property name="obey_child">False</property>
- <child>
- <object class="GtkHBox" id="hbox_trc_widget">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label6">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label16">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The TRC axis label">Response in</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox_vcgt_axis">
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkHBox" id="hbox_vcgt_axis">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label19">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The TRC axis label">Video card out</property>
- <property name="angle">90</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkAspectFrame" id="aspectframe_vcgt">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <property name="obey_child">False</property>
- <child>
- <object class="GtkHBox" id="hbox_vcgt_widget">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label20">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label21">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The TRC axis label">Response in</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkHSeparator" id="hseparator2">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox_profiles_details1">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkHBox" id="hbox_type">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox6">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_type">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The type of profile, e.g. display, scanner, etc.">Profile type:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox18">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_type">
- <property name="visible">True</property>
- <property name="label">input</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_colorspace">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox39">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_colorspace">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The profile colorspace, e.g. RGB">Colorspace:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox40">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_colorspace">
- <property name="visible">True</property>
- <property name="label">colorspace</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_datetime">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox36">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_datetime">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="When the profile was created">Created:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox37">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_datetime">
- <property name="visible">True</property>
- <property name="label">datetime</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_profile_manufacturer">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox10">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_profile_manufacturer">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The manufacturer of the profile">Device manufacturer:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox11">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_profile_manufacturer">
- <property name="visible">True</property>
- <property name="label">manufacturer</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_profile_model">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox34">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_profile_model">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The manufacturer of the profile">Device model:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox35">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_profile_model">
- <property name="visible">True</property>
- <property name="label">model</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_vcgt">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox48">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_vcgt">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="If the profile contains a display correction table">Display correction:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox49">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_vcgt">
- <property name="visible">True</property>
- <property name="label">yes</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">5</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_copyright">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox12">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_copyright">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The licence of the profile, normally non-free">License:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox30">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_copyright">
- <property name="visible">True</property>
- <property name="label">non-free</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">6</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_size">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox31">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_size">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The file size in bytes of the profile">File size:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox32">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_size">
- <property name="visible">True</property>
- <property name="label">input</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">7</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox_filename">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkHBox" id="hbox33">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_title_filename">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="The basename (the last section of the filename) of the profile">Filename:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox47">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label_filename">
- <property name="visible">True</property>
- <property name="label">filename</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="wrap_mode">word-char</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">3</property>
- <property name="position">8</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label_profiles">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="Tab title, currently installed profiles">Profiles</property>
- </object>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
<object class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="border_width">9</property>
@@ -2089,12 +1117,11 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="button_default">
- <property name="label" translatable="yes" comments="This is when the settings are set for all users, unless they have per-user settings themselves">_Set System Default</property>
+ <object class="GtkButton" id="button_viewer">
+ <property name="label" translatable="yes" comments="Button to view installed profiles">Pr_ofile Viewer</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Save these profiles for all users</property>
<property name="use_underline">True</property>
</object>
<packing>
@@ -2104,13 +1131,13 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="button_close">
- <property name="label">gtk-close</property>
+ <object class="GtkButton" id="button_default">
+ <property name="label" translatable="yes" comments="This is when the settings are set for all users, unless they have per-user settings themselves">_Set System Default</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Close this dialog</property>
- <property name="use_stock">True</property>
+ <property name="tooltip_text" translatable="yes">Save these profiles for all users</property>
+ <property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
@@ -2129,8 +1156,8 @@
</child>
<action-widgets>
<action-widget response="0">button_help</action-widget>
+ <action-widget response="0">button_viewer</action-widget>
<action-widget response="0">button_default</action-widget>
- <action-widget response="0">button_close</action-widget>
</action-widgets>
</object>
<object class="GtkDialog" id="dialog_virtual">
@@ -2559,49 +1586,28 @@
<action-widget response="0">button_assign_ok</action-widget>
</action-widgets>
</object>
- <object class="GtkSizeGroup" id="sizegroup_lists">
- <widgets>
- <widget name="scrolledwindow1"/>
- <widget name="scrolledwindow2"/>
- </widgets>
- </object>
<object class="GtkSizeGroup" id="sizegroup_defaults">
<widgets>
- <widget name="hbox43"/>
- <widget name="hbox46"/>
- <widget name="hbox15"/>
<widget name="hbox17"/>
+ <widget name="hbox15"/>
+ <widget name="hbox46"/>
+ <widget name="hbox43"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="sizegroup_devices">
<widgets>
- <widget name="hbox21"/>
- <widget name="hbox22"/>
- <widget name="hbox23"/>
<widget name="hbox53"/>
- </widgets>
- </object>
- <object class="GtkSizeGroup" id="sizegroup_profiles">
- <widgets>
- <widget name="hbox61"/>
- <widget name="hbox19"/>
- <widget name="hbox33"/>
- <widget name="hbox31"/>
- <widget name="hbox12"/>
- <widget name="hbox48"/>
- <widget name="hbox34"/>
- <widget name="hbox10"/>
- <widget name="hbox36"/>
- <widget name="hbox39"/>
- <widget name="hbox6"/>
+ <widget name="hbox23"/>
+ <widget name="hbox22"/>
+ <widget name="hbox21"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="sizegroup_combos">
<widgets>
- <widget name="combobox_rendering_softproof"/>
- <widget name="combobox_rendering_display"/>
- <widget name="combobox_space_cmyk"/>
<widget name="combobox_space_rgb"/>
+ <widget name="combobox_space_cmyk"/>
+ <widget name="combobox_rendering_display"/>
+ <widget name="combobox_rendering_softproof"/>
</widgets>
</object>
</interface>
diff --git a/data/gcm-viewer.ui b/data/gcm-viewer.ui
new file mode 100644
index 0000000..f70fdc2
--- /dev/null
+++ b/data/gcm-viewer.ui
@@ -0,0 +1,1108 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkDialog" id="dialog_viewer">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Color Profile Viewer</property>
+ <property name="window_position">center</property>
+ <property name="icon_name">preferences-system</property>
+ <property name="type_hint">normal</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">6</property>
+ <property name="right_padding">6</property>
+ <child>
+ <object class="GtkHBox" id="hbox5">
+ <property name="visible">True</property>
+ <property name="border_width">9</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkVBox" id="vbox_profiles">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_profiles">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox45">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="button_profile_import">
+ <property name="label" translatable="yes">_Add…</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_profile_delete">
+ <property name="label" translatable="yes">_Remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_sections1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">15</property>
+ <child>
+ <object class="GtkVBox" id="vbox13">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox_profile_info">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox_profiles_details">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkVBox" id="vbox_graph">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkHBox" id="hbox_graph">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox19">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_graph">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The graph representing the profile">Graph:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox38">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkComboBox" id="combobox_graph">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_graph_widgets">
+ <child>
+ <object class="GtkHBox" id="hbox61">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_graph1">
+ <property name="visible">True</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox60">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox_cie_axis">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHBox" id="hbox_cie_axis">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label17">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The CIE axis label, not to be confused with 'Y'">y</property>
+ <property name="angle">90</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAspectFrame" id="aspectframe_cie">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <property name="obey_child">False</property>
+ <child>
+ <object class="GtkHBox" id="hbox_cie_widget">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label18">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The CIE axis label, not to be confused with 'X'">x</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_trc_axis">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHBox" id="hbox_trc_axis">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The TRC axis label">Response out</property>
+ <property name="angle">90</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAspectFrame" id="aspectframe_trc">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <property name="obey_child">False</property>
+ <child>
+ <object class="GtkHBox" id="hbox_trc_widget">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The TRC axis label">Response in</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_vcgt_axis">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHBox" id="hbox_vcgt_axis">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label19">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The TRC axis label">Video card out</property>
+ <property name="angle">90</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAspectFrame" id="aspectframe_vcgt">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <property name="obey_child">False</property>
+ <child>
+ <object class="GtkHBox" id="hbox_vcgt_widget">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label20">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label21">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The TRC axis label">Response in</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_preview_input">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="This is an example image that is saved in sRGB gamut">sRGB example</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_preview_output">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">sRGB example</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHSeparator" id="hseparator2">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_profiles_details1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHBox" id="hbox_type">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_type">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The type of profile, e.g. display, scanner, etc.">Profile type:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox18">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_type">
+ <property name="visible">True</property>
+ <property name="label">input</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_colorspace">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox39">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_colorspace">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The profile colorspace, e.g. RGB">Colorspace:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox40">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_colorspace">
+ <property name="visible">True</property>
+ <property name="label">colorspace</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_datetime">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox36">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_datetime">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="When the profile was created">Created:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox37">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_datetime">
+ <property name="visible">True</property>
+ <property name="label">datetime</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_profile_manufacturer">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox10">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_profile_manufacturer">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The manufacturer of the profile">Device manufacturer:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox11">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_profile_manufacturer">
+ <property name="visible">True</property>
+ <property name="label">manufacturer</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_profile_model">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox34">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_profile_model">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The manufacturer of the profile">Device model:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox35">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_profile_model">
+ <property name="visible">True</property>
+ <property name="label">model</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_vcgt">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox48">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_vcgt">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="If the profile contains a display correction table">Display correction:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox49">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_vcgt">
+ <property name="visible">True</property>
+ <property name="label">yes</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_copyright">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox12">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_copyright">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The licence of the profile, normally non-free">License:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox30">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_copyright">
+ <property name="visible">True</property>
+ <property name="label">non-free</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_size">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox31">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_size">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The file size in bytes of the profile">File size:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox32">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_size">
+ <property name="visible">True</property>
+ <property name="label">input</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_filename">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox33">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_title_filename">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The basename (the last section of the filename) of the profile">Filename:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox47">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label_filename">
+ <property name="visible">True</property>
+ <property name="label">filename</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">3</property>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button_help">
+ <property name="label">gtk-help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Open the documentation</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_preferences">
+ <property name="label">gtk-preferences</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_close">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Close this dialog</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">button_help</action-widget>
+ <action-widget response="0">button_preferences</action-widget>
+ <action-widget response="0">button_close</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_profiles">
+ <widgets>
+ <widget name="hbox33"/>
+ <widget name="hbox31"/>
+ <widget name="hbox12"/>
+ <widget name="hbox48"/>
+ <widget name="hbox34"/>
+ <widget name="hbox10"/>
+ <widget name="hbox36"/>
+ <widget name="hbox39"/>
+ <widget name="hbox6"/>
+ <widget name="hbox61"/>
+ <widget name="hbox19"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/data/org.gnome.color-manager.gschema.xml b/data/org.gnome.color-manager.gschema.xml
index 8bdec98..d39632b 100644
--- a/data/org.gnome.color-manager.gschema.xml
+++ b/data/org.gnome.color-manager.gschema.xml
@@ -16,6 +16,8 @@
<value nick="cie-1931-xy" value="1"/>
<value nick="trc" value="2"/>
<value nick="vcgt" value="3"/>
+ <value nick="preview-input" value="4"/>
+ <value nick="preview-output" value="5"/>
</enum>
<schema id="org.gnome.color-manager" path="/apps/gnome-color-manager/">
<key name="default-gamma" type="d">
diff --git a/src/.gitignore b/src/.gitignore
index 791b7df..1010e14 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -7,7 +7,7 @@
.deps
gcm-apply
gcm-import
-gcm-prefs
+gcm-viewer
gcm-picker
gcm-inspect
gcm-session
diff --git a/src/Makefile.am b/src/Makefile.am
index 62da00d..c7880ab 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,6 +13,7 @@ INCLUDES = \
$(EXIV_CFLAGS) \
$(NOTIFY_CFLAGS) \
$(CANBERRA_CFLAGS) \
+ $(CONTROL_CENTER_CFLAGS) \
-DG_UDEV_API_IS_SUBJECT_TO_CHANGE \
-DGNOME_DESKTOP_USE_UNSTABLE_API \
$(GUDEV_CFLAGS) \
@@ -29,6 +30,9 @@ INCLUDES = \
introspectiondir = $(datadir)/dbus-1/interfaces
dist_introspection_DATA = org.gnome.ColorManager.xml
+ccpanelsdir = $(PANELS_DIR)
+ccpanels_LTLIBRARIES = libcolor.la
+
noinst_LIBRARIES = libgcmshared.a
libgcmshared_a_SOURCES = \
egg-debug.c \
@@ -108,7 +112,7 @@ bin_PROGRAMS = \
gcm-fix-profile \
gcm-dump-edid \
gcm-apply \
- gcm-prefs \
+ gcm-viewer \
gcm-session \
gcm-picker \
gcm-import
@@ -239,12 +243,12 @@ gcm_import_LDADD = \
gcm_import_CFLAGS = \
$(WARNINGFLAGS_C)
-gcm_prefs_SOURCES = \
+gcm_viewer_SOURCES = \
gcm-cell-renderer-profile.c \
gcm-cell-renderer-profile.h \
- gcm-prefs.c
+ gcm-viewer.c
-gcm_prefs_LDADD = \
+gcm_viewer_LDADD = \
libgcmshared.a \
$(GLIB_LIBS) \
$(X11_LIBS) \
@@ -258,10 +262,9 @@ gcm_prefs_LDADD = \
$(CUPS_LIBS) \
$(TIFF_LIBS) \
$(EXIF_LIBS) \
- $(CANBERRA_LIBS) \
-lm
-gcm_prefs_CFLAGS = \
+gcm_viewer_CFLAGS = \
$(WARNINGFLAGS_C)
gcm_picker_SOURCES = \
@@ -309,6 +312,33 @@ gcm_session_LDADD = \
gcm_session_CFLAGS = \
$(WARNINGFLAGS_C)
+libcolor_la_SOURCES = \
+ cc-color-panel.c \
+ cc-color-panel.h \
+ gcm-cell-renderer-profile.c \
+ gcm-cell-renderer-profile.h \
+ $(libgcmshared_a_SOURCES) \
+ $(NULL)
+
+libcolor_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(X11_LIBS) \
+ $(GNOMEDESKTOP_LIBS) \
+ $(GUDEV_LIBS) \
+ $(LCMS_LIBS) \
+ $(XORG_LIBS) \
+ $(GTK_LIBS) \
+ $(TIFF_LIBS) \
+ $(EXIF_LIBS) \
+ $(SANE_LIBS) \
+ $(NOTIFY_LIBS) \
+ $(CUPS_LIBS) \
+ $(CANBERRA_LIBS) \
+ $(CONTROL_CENTER_LIBS)
+
+libcolor_la_LDFLAGS = -avoid-version -module
+libcolor_la_CFLAGS = $(WARNINGFLAGS_C)
+
if HAVE_TESTS
check_PROGRAMS = \
diff --git a/src/cc-color-panel.c b/src/cc-color-panel.c
new file mode 100644
index 0000000..680bec0
--- /dev/null
+++ b/src/cc-color-panel.c
@@ -0,0 +1,2931 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <canberra-gtk.h>
+
+#include "egg-debug.h"
+
+#include "gcm-cell-renderer-profile.h"
+#include "gcm-calibrate-argyll.h"
+#include "gcm-cie-widget.h"
+#include "gcm-client.h"
+#include "gcm-colorimeter.h"
+#include "gcm-device-xrandr.h"
+#include "gcm-device-virtual.h"
+#include "gcm-exif.h"
+#include "gcm-profile.h"
+#include "gcm-profile-store.h"
+#include "gcm-trc-widget.h"
+#include "gcm-utils.h"
+#include "gcm-xyz.h"
+
+#include "egg-debug.h"
+
+#include "cc-color-panel.h"
+
+struct _CcColorPanelPrivate {
+ GtkBuilder *builder;
+ GtkListStore *list_store_devices;
+ GtkListStore *list_store_assign;
+ GcmDevice *current_device;
+ GcmProfileStore *profile_store;
+ GcmClient *gcm_client;
+ GcmColorimeter *colorimeter;
+ gboolean setting_up_device;
+ GtkWidget *main_window;
+ GtkWidget *info_bar_loading;
+ GtkWidget *info_bar_vcgt;
+ GtkWidget *info_bar_profiles;
+ GSettings *settings;
+};
+
+G_DEFINE_DYNAMIC_TYPE (CcColorPanel, cc_color_panel, CC_TYPE_PANEL)
+
+static void cc_color_panel_finalize (GObject *object);
+
+#define CC_COLOR_PREFS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_COLOR_PANEL, CcColorPanelPrivate))
+
+enum {
+ GCM_DEVICES_COLUMN_ID,
+ GCM_DEVICES_COLUMN_SORT,
+ GCM_DEVICES_COLUMN_ICON,
+ GCM_DEVICES_COLUMN_TITLE,
+ GCM_DEVICES_COLUMN_LAST
+};
+
+enum {
+ GCM_ASSIGN_COLUMN_SORT,
+ GCM_ASSIGN_COLUMN_PROFILE,
+ GCM_ASSIGN_COLUMN_IS_DEFAULT,
+ GCM_ASSIGN_COLUMN_LAST
+};
+
+enum {
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ GCM_PREFS_COMBO_COLUMN_PROFILE,
+ GCM_PREFS_COMBO_COLUMN_TYPE,
+ GCM_PREFS_COMBO_COLUMN_SORTABLE,
+ GCM_PREFS_COMBO_COLUMN_LAST
+};
+
+typedef enum {
+ GCM_PREFS_ENTRY_TYPE_PROFILE,
+ GCM_PREFS_ENTRY_TYPE_IMPORT,
+ GCM_PREFS_ENTRY_TYPE_LAST
+} GcmPrefsEntryType;
+
+static void cc_color_panel_devices_treeview_clicked_cb (GtkTreeSelection *selection, CcColorPanel *panel);
+static void cc_color_panel_profile_store_changed_cb (GcmProfileStore *profile_store, CcColorPanel *panel);
+
+#define GCM_PREFS_TREEVIEW_MAIN_WIDTH 350 /* px */
+#define GCM_PREFS_TREEVIEW_PROFILES_WIDTH 450 /* px */
+
+/**
+ * cc_color_panel_error_dialog:
+ **/
+static void
+cc_color_panel_error_dialog (CcColorPanel *panel, const gchar *title, const gchar *message)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (panel->priv->main_window),
+ GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE, "%s", title);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+/**
+ * cc_color_panel_set_default:
+ **/
+static gboolean
+cc_color_panel_set_default (CcColorPanel *panel, GcmDevice *device)
+{
+ GError *error = NULL;
+ gboolean ret = FALSE;
+ gchar *cmdline = NULL;
+ const gchar *filename;
+ const gchar *id;
+ gchar *install_cmd = NULL;
+
+ /* nothing set */
+ id = gcm_device_get_id (device);
+ filename = gcm_device_get_default_profile_filename (device);
+ if (filename == NULL) {
+ egg_debug ("no filename for %s", id);
+ goto out;
+ }
+
+ /* run using PolicyKit */
+ install_cmd = g_build_filename (SBINDIR, "gcm-install-system-wide", NULL);
+ cmdline = g_strdup_printf ("pkexec %s --id %s \"%s\"", install_cmd, id, filename);
+ egg_debug ("running: %s", cmdline);
+ ret = g_spawn_command_line_sync (cmdline, NULL, NULL, NULL, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not save for all users */
+ cc_color_panel_error_dialog (panel, _("Failed to save defaults for all users"), error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ g_free (install_cmd);
+ g_free (cmdline);
+ return ret;
+}
+
+/**
+ * cc_color_panel_combobox_add_profile:
+ **/
+static void
+cc_color_panel_combobox_add_profile (GtkWidget *widget, GcmProfile *profile, GcmPrefsEntryType entry_type, GtkTreeIter *iter)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter_tmp;
+ const gchar *description;
+ gchar *sortable;
+
+ /* iter is optional */
+ if (iter == NULL)
+ iter = &iter_tmp;
+
+ /* use description */
+ if (entry_type == GCM_PREFS_ENTRY_TYPE_IMPORT) {
+ /* TRANSLATORS: this is where the user can click and import a profile */
+ description = _("Other profileâ?¦");
+ sortable = g_strdup ("9");
+ } else {
+ description = gcm_profile_get_description (profile);
+ sortable = g_strdup_printf ("5%s", description);
+ }
+
+ /* also add profile */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_list_store_append (GTK_LIST_STORE(model), iter);
+ gtk_list_store_set (GTK_LIST_STORE(model), iter,
+ GCM_PREFS_COMBO_COLUMN_TEXT, description,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
+ GCM_PREFS_COMBO_COLUMN_TYPE, entry_type,
+ GCM_PREFS_COMBO_COLUMN_SORTABLE, sortable,
+ -1);
+ g_free (sortable);
+}
+
+/**
+ * cc_color_panel_default_cb:
+ **/
+static void
+cc_color_panel_default_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ GPtrArray *array = NULL;
+ GcmDevice *device;
+ GcmDeviceKind kind;
+ gboolean ret;
+ guint i;
+
+ /* set for each output */
+ array = gcm_client_get_devices (panel->priv->gcm_client);
+ for (i=0; i<array->len; i++) {
+ device = g_ptr_array_index (array, i);
+
+ /* not a xrandr panel */
+ kind = gcm_device_get_kind (device);
+ if (kind != GCM_DEVICE_KIND_DISPLAY)
+ continue;
+
+ /* set for this device */
+ ret = cc_color_panel_set_default (panel, device);
+ if (!ret)
+ break;
+ }
+ g_ptr_array_unref (array);
+}
+
+/**
+ * cc_color_panel_help_cb:
+ **/
+static void
+cc_color_panel_help_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ gcm_gnome_help ("preferences");
+}
+
+/**
+ * cc_color_panel_viewer_cb:
+ **/
+static void
+cc_color_panel_viewer_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ gboolean ret;
+ GError *error = NULL;
+ guint xid;
+ gchar *command;
+
+ /* get xid */
+ xid = gdk_x11_drawable_get_xid (gtk_widget_get_window (GTK_WIDGET (panel->priv->main_window)));
+
+ /* run with modal set */
+ command = g_strdup_printf ("%s/gcm-viewer --parent-window %u", BINDIR, xid);
+ egg_debug ("running: %s", command);
+ ret = g_spawn_command_line_async (command, &error);
+ if (!ret) {
+ egg_warning ("failed to run prefs: %s", error->message);
+ g_error_free (error);
+ }
+ g_free (command);
+}
+
+/**
+ * cc_color_panel_calibrate_display:
+ **/
+static gboolean
+cc_color_panel_calibrate_display (CcColorPanel *panel, GcmCalibrate *calibrate)
+{
+ gboolean ret = FALSE;
+ gboolean ret_tmp;
+ GError *error = NULL;
+ GtkWindow *window;
+
+ /* no device */
+ if (panel->priv->current_device == NULL)
+ goto out;
+
+ /* set properties from the device */
+ ret = gcm_calibrate_set_from_device (calibrate, panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to calibrate: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* run each task in order */
+ window = GTK_WINDOW(panel->priv->main_window);
+ ret = gcm_calibrate_display (calibrate, window, &error);
+ if (!ret) {
+ egg_warning ("failed to calibrate: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ /* need to set the gamma back to the default after calibration */
+ error = NULL;
+ ret_tmp = gcm_device_apply (panel->priv->current_device, &error);
+ if (!ret_tmp) {
+ egg_warning ("failed to apply profile: %s", error->message);
+ g_error_free (error);
+ }
+ return ret;
+}
+
+/**
+ * cc_color_panel_calibrate_device:
+ **/
+static gboolean
+cc_color_panel_calibrate_device (CcColorPanel *panel, GcmCalibrate *calibrate)
+{
+ gboolean ret = FALSE;
+ GError *error = NULL;
+ GtkWindow *window;
+
+ /* set defaults from device */
+ ret = gcm_calibrate_set_from_device (calibrate, panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to calibrate: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* do each step */
+ window = GTK_WINDOW(panel->priv->main_window);
+ ret = gcm_calibrate_device (calibrate, window, &error);
+ if (!ret) {
+ if (error->code != GCM_CALIBRATE_ERROR_USER_ABORT) {
+ /* TRANSLATORS: could not calibrate */
+ cc_color_panel_error_dialog (panel, _("Failed to calibrate device"), error->message);
+ } else {
+ egg_warning ("failed to calibrate: %s", error->message);
+ }
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return ret;
+}
+
+/**
+ * cc_color_panel_calibrate_printer:
+ **/
+static gboolean
+cc_color_panel_calibrate_printer (CcColorPanel *panel, GcmCalibrate *calibrate)
+{
+ gboolean ret = FALSE;
+ GError *error = NULL;
+ GtkWindow *window;
+
+ /* set defaults from device */
+ ret = gcm_calibrate_set_from_device (calibrate, panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to calibrate: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* do each step */
+ window = GTK_WINDOW(panel->priv->main_window);
+ ret = gcm_calibrate_printer (calibrate, window, &error);
+ if (!ret) {
+ if (error->code != GCM_CALIBRATE_ERROR_USER_ABORT) {
+ /* TRANSLATORS: could not calibrate */
+ cc_color_panel_error_dialog (panel, _("Failed to calibrate printer"), error->message);
+ } else {
+ egg_warning ("failed to calibrate: %s", error->message);
+ }
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return ret;
+}
+
+/**
+ * cc_color_panel_file_chooser_get_icc_profile:
+ **/
+static GFile *
+cc_color_panel_file_chooser_get_icc_profile (CcColorPanel *panel)
+{
+ GtkWindow *window;
+ GtkWidget *dialog;
+ GFile *file = NULL;
+ GtkFileFilter *filter;
+
+ /* create new dialog */
+ window = GTK_WINDOW(gtk_builder_get_object (panel->priv->builder, "dialog_assign"));
+ /* TRANSLATORS: dialog for file->open dialog */
+ dialog = gtk_file_chooser_dialog_new (_("Select ICC Profile File"), window,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Import"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(dialog), g_get_home_dir ());
+ gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER(dialog), FALSE);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER(dialog), FALSE);
+
+ /* setup the filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_mime_type (filter, "application/vnd.iccprofile");
+
+ /* we can remove this when we depend on a new shared-mime-info */
+ gtk_file_filter_add_pattern (filter, "*.icc");
+ gtk_file_filter_add_pattern (filter, "*.icm");
+ gtk_file_filter_add_pattern (filter, "*.ICC");
+ gtk_file_filter_add_pattern (filter, "*.ICM");
+
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("Supported ICC profiles"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* setup the all files filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* did user choose file */
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER(dialog));
+
+ /* we're done */
+ gtk_widget_destroy (dialog);
+
+ /* or NULL for missing */
+ return file;
+}
+
+/**
+ * cc_color_panel_profile_import_file:
+ **/
+static gboolean
+cc_color_panel_profile_import_file (CcColorPanel *panel, GFile *file)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GFile *destination = NULL;
+
+ /* check if correct type */
+ ret = gcm_utils_is_icc_profile (file);
+ if (!ret) {
+ egg_debug ("not a ICC profile");
+ goto out;
+ }
+
+ /* copy icc file to ~/.color/icc */
+ destination = gcm_utils_get_profile_destination (file);
+ ret = gcm_utils_mkdir_and_copy (file, destination, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not read file */
+ cc_color_panel_error_dialog (panel, _("Failed to copy file"), error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (destination != NULL)
+ g_object_unref (destination);
+ return ret;
+}
+
+/**
+ * cc_color_panel_profile_add_virtual_file:
+ **/
+static gboolean
+cc_color_panel_profile_add_virtual_file (CcColorPanel *panel, GFile *file)
+{
+ gboolean ret;
+ GcmExif *exif;
+ GError *error = NULL;
+ GcmDevice *device = NULL;
+
+ /* parse file */
+ exif = gcm_exif_new ();
+ ret = gcm_exif_parse (exif, file, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not add virtual device */
+ if (error->domain != GCM_EXIF_ERROR ||
+ error->code != GCM_EXIF_ERROR_NO_SUPPORT)
+ cc_color_panel_error_dialog (panel, _("Failed to get metadata from image"), error->message);
+ else
+ egg_debug ("not a supported image format: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* create device */
+ device = gcm_device_virtual_new ();
+ ret = gcm_device_virtual_create_from_params (GCM_DEVICE_VIRTUAL (device),
+ gcm_exif_get_device_kind (exif),
+ gcm_exif_get_model (exif),
+ gcm_exif_get_manufacturer (exif),
+ gcm_exif_get_serial (exif),
+ GCM_COLORSPACE_RGB);
+ if (!ret) {
+ /* TRANSLATORS: could not add virtual device */
+ cc_color_panel_error_dialog (panel, _("Failed to create virtual device"), NULL);
+ goto out;
+ }
+
+ /* save what we've got */
+ ret = gcm_device_save (device, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not add virtual device */
+ cc_color_panel_error_dialog (panel, _("Failed to save virtual device"), error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* add to the device list */
+ ret = gcm_client_add_device (panel->priv->gcm_client, device, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not add virtual device */
+ cc_color_panel_error_dialog (panel, _("Failed to add virtual device"), error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ g_object_unref (exif);
+ if (device != NULL)
+ g_object_unref (device);
+ return ret;
+}
+
+/**
+ * cc_color_panel_drag_data_received_cb:
+ **/
+static void
+cc_color_panel_drag_data_received_cb (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint _time, CcColorPanel *panel)
+{
+ const guchar *filename;
+ gchar **filenames = NULL;
+ GFile *file = NULL;
+ guint i;
+ gboolean ret;
+ gboolean success = FALSE;
+
+ /* get filenames */
+ filename = gtk_selection_data_get_data (data);
+ if (filename == NULL)
+ goto out;
+
+ /* import this */
+ egg_debug ("dropped: %p (%s)", data, filename);
+
+ /* split, as multiple drag targets are accepted */
+ filenames = g_strsplit_set ((const gchar *)filename, "\r\n", -1);
+ for (i=0; filenames[i]!=NULL; i++) {
+
+ /* blank entry */
+ if (filenames[i][0] == '\0')
+ continue;
+
+ /* convert the URI */
+ file = g_file_new_for_uri (filenames[i]);
+
+ /* try to import it */
+ ret = cc_color_panel_profile_import_file (panel, file);
+ if (ret)
+ success = TRUE;
+
+ /* try to add a virtual profile with it */
+ ret = cc_color_panel_profile_add_virtual_file (panel, file);
+ if (ret)
+ success = TRUE;
+
+ g_object_unref (file);
+ }
+
+out:
+ gtk_drag_finish (context, success, FALSE, _time);
+ g_strfreev (filenames);
+}
+
+/**
+ * cc_color_panel_virtual_set_from_file:
+ **/
+static gboolean
+cc_color_panel_virtual_set_from_file (CcColorPanel *panel, GFile *file)
+{
+ gboolean ret;
+ GcmExif *exif;
+ GError *error = NULL;
+ const gchar *model;
+ const gchar *manufacturer;
+ GtkWidget *widget;
+
+ /* parse file */
+ exif = gcm_exif_new ();
+ ret = gcm_exif_parse (exif, file, &error);
+ if (!ret) {
+ egg_warning ("failed to parse file: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* set model and manufacturer */
+ model = gcm_exif_get_model (exif);
+ if (model != NULL) {
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_model"));
+ gtk_entry_set_text (GTK_ENTRY (widget), model);
+ }
+ manufacturer = gcm_exif_get_manufacturer (exif);
+ if (manufacturer != NULL) {
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_manufacturer"));
+ gtk_entry_set_text (GTK_ENTRY (widget), manufacturer);
+ }
+
+ /* set type */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_virtual_type"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX(widget), GCM_DEVICE_KIND_CAMERA - 2);
+out:
+ g_object_unref (exif);
+ return ret;
+}
+
+/**
+ * cc_color_panel_virtual_drag_data_received_cb:
+ **/
+static void
+cc_color_panel_virtual_drag_data_received_cb (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
+ GtkSelectionData *data, guint info, guint _time, CcColorPanel *panel)
+{
+ const guchar *filename;
+ gchar **filenames = NULL;
+ GFile *file = NULL;
+ guint i;
+ gboolean ret;
+
+ g_return_if_fail (CC_IS_COLOR_PANEL (panel));
+
+ /* get filenames */
+ filename = gtk_selection_data_get_data (data);
+ if (filename == NULL) {
+ gtk_drag_finish (context, FALSE, FALSE, _time);
+ goto out;
+ }
+
+ /* import this */
+ egg_debug ("dropped: %p (%s)", data, filename);
+
+ /* split, as multiple drag targets are accepted */
+ filenames = g_strsplit_set ((const gchar *)filename, "\r\n", -1);
+ for (i=0; filenames[i]!=NULL; i++) {
+
+ /* blank entry */
+ if (filenames[i][0] == '\0')
+ continue;
+
+ /* check this is an ICC profile */
+ egg_debug ("trying to set %s", filenames[i]);
+ file = g_file_new_for_uri (filenames[i]);
+ ret = cc_color_panel_virtual_set_from_file (panel, file);
+ if (!ret) {
+ egg_debug ("%s did not set from file correctly", filenames[i]);
+ gtk_drag_finish (context, FALSE, FALSE, _time);
+ goto out;
+ }
+ g_object_unref (file);
+ file = NULL;
+ }
+
+ gtk_drag_finish (context, TRUE, FALSE, _time);
+out:
+ if (file != NULL)
+ g_object_unref (file);
+ g_strfreev (filenames);
+}
+
+/**
+ * cc_color_panel_ensure_argyllcms_installed:
+ **/
+static gboolean
+cc_color_panel_ensure_argyllcms_installed (CcColorPanel *panel)
+{
+ gboolean ret;
+ GtkWindow *window;
+ GtkWidget *dialog;
+ GtkResponseType response;
+ GString *string = NULL;
+
+ /* find whether argyllcms is installed using a tool which should exist */
+ ret = g_file_test ("/usr/bin/dispcal", G_FILE_TEST_EXISTS);
+ if (ret)
+ goto out;
+
+#ifndef HAVE_PACKAGEKIT
+ egg_warning ("cannot install: this package was not compiled with --enable-packagekit");
+ goto out;
+#endif
+
+ /* ask the user to confirm */
+ window = GTK_WINDOW(panel->priv->main_window);
+ dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+ /* TRANSLATORS: title, usually we can tell based on the EDID data or output name */
+ _("Install calibration and profiling software?"));
+
+ string = g_string_new ("");
+ /* TRANSLATORS: dialog message saying the argyllcms is not installed */
+ g_string_append_printf (string, "%s\n", _("Calibration and profiling software is not installed."));
+ /* TRANSLATORS: dialog message saying the color targets are not installed */
+ g_string_append_printf (string, "%s", _("These tools are required to build color profiles for devices."));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", string->str);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
+ /* TRANSLATORS: button, skip installing a package */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Do not install"), GTK_RESPONSE_CANCEL);
+ /* TRANSLATORS: button, install a package */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install"), GTK_RESPONSE_YES);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ /* only install if the user wanted to */
+ if (response != GTK_RESPONSE_YES)
+ goto out;
+
+ /* do the install */
+ ret = gcm_utils_install_package (GCM_PREFS_PACKAGE_NAME_ARGYLLCMS, window);
+out:
+ if (string != NULL)
+ g_string_free (string, TRUE);
+ return ret;
+}
+
+/**
+ * cc_color_panel_calibrate_cb:
+ **/
+static void
+cc_color_panel_calibrate_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ GcmCalibrate *calibrate = NULL;
+ GcmDeviceKind kind;
+ gboolean ret;
+ GError *error = NULL;
+ const gchar *filename;
+ guint i;
+ const gchar *name;
+ GcmProfile *profile;
+ GPtrArray *profile_array = NULL;
+ GFile *file = NULL;
+ GFile *dest = NULL;
+ gchar *destination = NULL;
+
+ /* ensure argyllcms is installed */
+ ret = cc_color_panel_ensure_argyllcms_installed (panel);
+ if (!ret)
+ goto out;
+
+ /* create new calibration object */
+ calibrate = GCM_CALIBRATE(gcm_calibrate_argyll_new ());
+
+ /* choose the correct kind of calibration */
+ kind = gcm_device_get_kind (panel->priv->current_device);
+ switch (kind) {
+ case GCM_DEVICE_KIND_DISPLAY:
+ ret = cc_color_panel_calibrate_display (panel, calibrate);
+ break;
+ case GCM_DEVICE_KIND_SCANNER:
+ case GCM_DEVICE_KIND_CAMERA:
+ ret = cc_color_panel_calibrate_device (panel, calibrate);
+ break;
+ case GCM_DEVICE_KIND_PRINTER:
+ ret = cc_color_panel_calibrate_printer (panel, calibrate);
+ break;
+ default:
+ egg_warning ("calibration and/or profiling not supported for this device");
+ goto out;
+ }
+
+ /* we failed to calibrate */
+ if (!ret) {
+ egg_warning ("failed to calibrate");
+ goto out;
+ }
+
+ /* failed to get profile */
+ filename = gcm_calibrate_get_filename_result (calibrate);
+ if (filename == NULL) {
+ egg_warning ("failed to get filename from calibration");
+ goto out;
+ }
+
+ /* copy the ICC file to the proper location */
+ file = g_file_new_for_path (filename);
+ dest = gcm_utils_get_profile_destination (file);
+ ret = gcm_utils_mkdir_and_copy (file, dest, &error);
+ if (!ret) {
+ egg_warning ("failed to calibrate: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* find an existing profile of this name */
+ profile_array = gcm_device_get_profiles (panel->priv->current_device);
+ destination = g_file_get_path (dest);
+ for (i=0; i<profile_array->len; i++) {
+ profile = g_ptr_array_index (profile_array, i);
+ name = gcm_profile_get_filename (profile);
+ if (g_strcmp0 (name, destination) == 0) {
+ egg_debug ("found existing profile: %s", destination);
+ break;
+ }
+ }
+
+ /* we didn't find an existing profile */
+ if (i == profile_array->len) {
+ egg_debug ("adding: %s", destination);
+
+ /* set this default */
+ gcm_device_set_default_profile_filename (panel->priv->current_device, destination);
+ ret = gcm_device_save (panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to save default: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ }
+
+ /* remove temporary file */
+ g_unlink (filename);
+
+ /* play sound from the naming spec */
+ ca_context_play (ca_gtk_context_get (), 0,
+ CA_PROP_EVENT_ID, "complete",
+ /* TRANSLATORS: this is the application name for libcanberra */
+ CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
+ /* TRANSLATORS: this is the sound description */
+ CA_PROP_EVENT_DESCRIPTION, _("Profiling completed"), NULL);
+out:
+ g_free (destination);
+ if (profile_array != NULL)
+ g_ptr_array_unref (profile_array);
+ if (calibrate != NULL)
+ g_object_unref (calibrate);
+ if (file != NULL)
+ g_object_unref (file);
+ if (dest != NULL)
+ g_object_unref (dest);
+}
+
+/**
+ * cc_color_panel_device_add_cb:
+ **/
+static void
+cc_color_panel_device_add_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ /* show ui */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_virtual"));
+ gtk_widget_show (widget);
+ gtk_window_set_transient_for (GTK_WINDOW (widget), GTK_WINDOW (panel->priv->main_window));
+
+ /* clear entries */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_virtual_type"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX(widget), 0);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_model"));
+ gtk_entry_set_text (GTK_ENTRY (widget), "");
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_manufacturer"));
+ gtk_entry_set_text (GTK_ENTRY (widget), "");
+}
+
+/**
+ * cc_color_panel_is_profile_suitable_for_device:
+ **/
+static gboolean
+cc_color_panel_is_profile_suitable_for_device (GcmProfile *profile, GcmDevice *device)
+{
+ GcmProfileKind profile_kind_tmp;
+ GcmProfileKind profile_kind;
+ GcmColorspace profile_colorspace;
+ GcmColorspace device_colorspace;
+ gboolean ret = FALSE;
+ GcmDeviceKind device_kind;
+
+ /* not the right colorspace */
+ device_colorspace = gcm_device_get_colorspace (device);
+ profile_colorspace = gcm_profile_get_colorspace (profile);
+ if (device_colorspace != profile_colorspace)
+ goto out;
+
+ /* not the correct kind */
+ device_kind = gcm_device_get_kind (device);
+ profile_kind_tmp = gcm_profile_get_kind (profile);
+ profile_kind = gcm_utils_device_kind_to_profile_kind (device_kind);
+ if (profile_kind_tmp != profile_kind)
+ goto out;
+
+ /* success */
+ ret = TRUE;
+out:
+ return ret;
+}
+
+/**
+ * cc_color_panel_add_profiles_suitable_for_devices:
+ **/
+static void
+cc_color_panel_add_profiles_suitable_for_devices (CcColorPanel *panel, GtkWidget *widget, const gchar *profile_filename)
+{
+ GtkTreeModel *model;
+ guint i;
+ gboolean ret;
+ GcmProfile *profile;
+ GPtrArray *profile_array;
+ GtkTreeIter iter;
+
+ /* clear existing entries */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_list_store_clear (GTK_LIST_STORE (model));
+
+ /* get new list */
+ profile_array = gcm_profile_store_get_array (panel->priv->profile_store);
+
+ /* add profiles of the right kind */
+ for (i=0; i<profile_array->len; i++) {
+ profile = g_ptr_array_index (profile_array, i);
+
+ /* don't add the current profile */
+ if (g_strcmp0 (gcm_profile_get_filename (profile), profile_filename) == 0)
+ continue;
+
+ /* only add correct types */
+ ret = cc_color_panel_is_profile_suitable_for_device (profile, panel->priv->current_device);
+ if (!ret)
+ continue;
+
+ /* add */
+ cc_color_panel_combobox_add_profile (widget, profile, GCM_PREFS_ENTRY_TYPE_PROFILE, &iter);
+ }
+
+ /* add a import entry */
+ cc_color_panel_combobox_add_profile (widget, NULL, GCM_PREFS_ENTRY_TYPE_IMPORT, NULL);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ g_ptr_array_unref (profile_array);
+}
+
+/**
+ * cc_color_panel_assign_save_profiles_for_device:
+ **/
+static void
+cc_color_panel_assign_save_profiles_for_device (CcColorPanel *panel, GcmDevice *device)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gboolean is_default;
+ GcmProfile *profile;
+ GPtrArray *array;
+ gboolean ret;
+ GError *error = NULL;
+
+ /* create empty array */
+ array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+ /* get first element */
+ model = GTK_TREE_MODEL (panel->priv->list_store_assign);
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ if (!ret)
+ goto set_profiles;
+
+ /* add default device first */
+ do {
+ gtk_tree_model_get (model, &iter,
+ GCM_ASSIGN_COLUMN_PROFILE, &profile,
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+ -1);
+ if (is_default)
+ g_ptr_array_add (array, g_object_ref (profile));
+ g_object_unref (profile);
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ /* add non-default devices next */
+ gtk_tree_model_get_iter_first (model, &iter);
+ do {
+ gtk_tree_model_get (model, &iter,
+ GCM_ASSIGN_COLUMN_PROFILE, &profile,
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+ -1);
+ if (!is_default)
+ g_ptr_array_add (array, g_object_ref (profile));
+ g_object_unref (profile);
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+set_profiles:
+ /* save new array */
+ gcm_device_set_profiles (device, array);
+
+ /* save */
+ ret = gcm_device_save (panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to save config: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* set the profile */
+ ret = gcm_device_apply (panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to apply profile: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ g_ptr_array_unref (array);
+}
+
+/**
+ * cc_color_panel_assign_add_cb:
+ **/
+static void
+cc_color_panel_assign_add_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ const gchar *profile_filename;
+
+ /* add profiles of the right kind */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_profile"));
+ profile_filename = gcm_device_get_default_profile_filename (panel->priv->current_device);
+ cc_color_panel_add_profiles_suitable_for_devices (panel, widget, profile_filename);
+
+ /* show the dialog */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_assign"));
+ gtk_widget_show (widget);
+ gtk_window_set_transient_for (GTK_WINDOW (widget), GTK_WINDOW (panel->priv->main_window));
+}
+
+/**
+ * cc_color_panel_assign_remove_cb:
+ **/
+static void
+cc_color_panel_assign_remove_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ gboolean is_default;
+ gboolean ret;
+
+ /* get the selected row */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_assign"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ egg_debug ("no row selected");
+ goto out;
+ }
+
+ /* if the profile is default, then we'll have to make the first profile default */
+ gtk_tree_model_get (model, &iter,
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+ -1);
+
+ /* remove this entry */
+ gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
+
+ /* /something/ has to be the default profile */
+ if (is_default) {
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ if (ret) {
+ gtk_list_store_set (panel->priv->list_store_assign, &iter,
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, TRUE,
+ GCM_ASSIGN_COLUMN_SORT, "0",
+ -1);
+ do {
+ gtk_list_store_set (panel->priv->list_store_assign, &iter,
+ GCM_ASSIGN_COLUMN_SORT, "1",
+ -1);
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+ }
+
+ /* save device */
+ cc_color_panel_assign_save_profiles_for_device (panel, panel->priv->current_device);
+out:
+ return;
+}
+
+/**
+ * cc_color_panel_assign_make_default_internal:
+ **/
+static void
+cc_color_panel_assign_make_default_internal (CcColorPanel *panel, GtkTreeModel *model, GtkTreeIter *iter_selected)
+{
+ GtkTreeIter iter;
+ GtkWidget *widget;
+
+ /* make none of the devices default */
+ gtk_tree_model_get_iter_first (model, &iter);
+ do {
+ gtk_list_store_set (panel->priv->list_store_assign, &iter,
+ GCM_ASSIGN_COLUMN_SORT, "1",
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, FALSE,
+ -1);
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ /* make the selected device default */
+ gtk_list_store_set (panel->priv->list_store_assign, iter_selected,
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, TRUE,
+ GCM_ASSIGN_COLUMN_SORT, "0",
+ -1);
+
+ /* set button insensitive */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_make_default"));
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ /* save device */
+ cc_color_panel_assign_save_profiles_for_device (panel, panel->priv->current_device);
+}
+
+/**
+ * cc_color_panel_assign_make_default_cb:
+ **/
+static void
+cc_color_panel_assign_make_default_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+
+ /* get the selected row */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_assign"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ egg_debug ("no row selected");
+ return;
+ }
+
+ /* make this profile the default */
+ cc_color_panel_assign_make_default_internal (panel, model, &iter);
+}
+
+/**
+ * cc_color_panel_button_virtual_add_cb:
+ **/
+static void
+cc_color_panel_button_virtual_add_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ GcmDeviceKind device_kind;
+ GcmDevice *device;
+ const gchar *model;
+ const gchar *manufacturer;
+ gboolean ret;
+ GError *error = NULL;
+
+ /* get device details */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_virtual_type"));
+ device_kind = gtk_combo_box_get_active (GTK_COMBO_BOX(widget)) + 2;
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_model"));
+ model = gtk_entry_get_text (GTK_ENTRY (widget));
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_manufacturer"));
+ manufacturer = gtk_entry_get_text (GTK_ENTRY (widget));
+
+ /* create device */
+ device = gcm_device_virtual_new ();
+ ret = gcm_device_virtual_create_from_params (GCM_DEVICE_VIRTUAL (device),
+ device_kind, model, manufacturer,
+ NULL, GCM_COLORSPACE_RGB);
+ if (!ret) {
+ /* TRANSLATORS: could not add virtual device */
+ cc_color_panel_error_dialog (panel, _("Failed to create virtual device"), NULL);
+ goto out;
+ }
+
+ /* save what we've got */
+ ret = gcm_device_save (device, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not add virtual device */
+ cc_color_panel_error_dialog (panel, _("Failed to save virtual device"), error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* add to the device list */
+ ret = gcm_client_add_device (panel->priv->gcm_client, device, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not add virtual device */
+ cc_color_panel_error_dialog (panel, _("Failed to add virtual device"), error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+out:
+ /* we're done */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_virtual"));
+ gtk_widget_hide (widget);
+}
+
+/**
+ * cc_color_panel_button_virtual_cancel_cb:
+ **/
+static void
+cc_color_panel_button_virtual_cancel_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_virtual"));
+ gtk_widget_hide (widget);
+}
+
+/**
+ * cc_color_panel_virtual_delete_event_cb:
+ **/
+static gboolean
+cc_color_panel_virtual_delete_event_cb (GtkWidget *widget, GdkEvent *event, CcColorPanel *panel)
+{
+ cc_color_panel_button_virtual_cancel_cb (widget, panel);
+ return TRUE;
+}
+
+/**
+ * cc_color_panel_button_assign_cancel_cb:
+ **/
+static void
+cc_color_panel_button_assign_cancel_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_assign"));
+ gtk_widget_hide (widget);
+}
+
+/**
+ * cc_color_panel_button_assign_ok_cb:
+ **/
+static void
+cc_color_panel_button_assign_ok_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GcmProfile *profile;
+ gboolean is_default = FALSE;
+ gboolean ret;
+
+ /* hide window */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_assign"));
+ gtk_widget_hide (widget);
+
+ /* get entry */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_profile"));
+ ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
+ if (!ret)
+ return;
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* if list is empty, we want this to be the default item */
+ model = GTK_TREE_MODEL (panel->priv->list_store_assign);
+ is_default = !gtk_tree_model_get_iter_first (model, &iter);
+
+ /* add profile */
+ gtk_list_store_append (panel->priv->list_store_assign, &iter);
+ gtk_list_store_set (panel->priv->list_store_assign, &iter,
+ GCM_ASSIGN_COLUMN_PROFILE, profile,
+ GCM_ASSIGN_COLUMN_SORT, is_default ? "0" : "1",
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, is_default,
+ -1);
+
+ /* save device */
+ cc_color_panel_assign_save_profiles_for_device (panel, panel->priv->current_device);
+}
+
+/**
+ * cc_color_panel_assign_delete_event_cb:
+ **/
+static gboolean
+cc_color_panel_assign_delete_event_cb (GtkWidget *widget, GdkEvent *event, CcColorPanel *panel)
+{
+ cc_color_panel_button_assign_cancel_cb (widget, panel);
+ return TRUE;
+}
+
+/**
+ * cc_color_panel_delete_cb:
+ **/
+static void
+cc_color_panel_delete_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* try to delete device */
+ ret = gcm_client_delete_device (panel->priv->gcm_client, panel->priv->current_device, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not read file */
+ cc_color_panel_error_dialog (panel, _("Failed to delete file"), error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * cc_color_panel_reset_cb:
+ **/
+static void
+cc_color_panel_reset_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ panel->priv->setting_up_device = TRUE;
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_gamma"));
+ gtk_range_set_value (GTK_RANGE (widget), 1.0f);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_brightness"));
+ gtk_range_set_value (GTK_RANGE (widget), 0.0f);
+ panel->priv->setting_up_device = FALSE;
+ /* we only want one save, not three */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_contrast"));
+ gtk_range_set_value (GTK_RANGE (widget), 1.0f);
+}
+
+/**
+ * cc_color_panel_add_devices_columns:
+ **/
+static void
+cc_color_panel_add_devices_columns (CcColorPanel *panel, GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* image */
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DND, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("", renderer,
+ "icon-name", GCM_DEVICES_COLUMN_ICON, NULL);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* set minimum width */
+ gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_PREFS_TREEVIEW_MAIN_WIDTH, -1);
+
+ /* column for text */
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "wrap-mode", PANGO_WRAP_WORD,
+ "wrap-width", GCM_PREFS_TREEVIEW_MAIN_WIDTH - 62,
+ NULL);
+ column = gtk_tree_view_column_new_with_attributes ("", renderer,
+ "markup", GCM_DEVICES_COLUMN_TITLE, NULL);
+ gtk_tree_view_column_set_sort_column_id (column, GCM_DEVICES_COLUMN_SORT);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (panel->priv->list_store_devices), GCM_DEVICES_COLUMN_SORT, GTK_SORT_ASCENDING);
+ gtk_tree_view_append_column (treeview, column);
+ gtk_tree_view_column_set_expand (column, TRUE);
+}
+
+/**
+ * cc_color_panel_add_assign_columns:
+ **/
+static void
+cc_color_panel_add_assign_columns (CcColorPanel *panel, GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* set minimum width */
+ gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_PREFS_TREEVIEW_PROFILES_WIDTH, -1);
+
+ /* column for text */
+ renderer = gcm_cell_renderer_profile_new ();
+ g_object_set (renderer,
+ "wrap-mode", PANGO_WRAP_WORD,
+ "wrap-width", GCM_PREFS_TREEVIEW_PROFILES_WIDTH - 62,
+ NULL);
+ column = gtk_tree_view_column_new_with_attributes ("", renderer,
+ "profile", GCM_ASSIGN_COLUMN_PROFILE,
+ "is-default", GCM_ASSIGN_COLUMN_IS_DEFAULT,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id (column, GCM_ASSIGN_COLUMN_SORT);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (panel->priv->list_store_assign), GCM_ASSIGN_COLUMN_SORT, GTK_SORT_ASCENDING);
+ gtk_tree_view_append_column (treeview, column);
+ gtk_tree_view_column_set_expand (column, TRUE);
+}
+
+/**
+ * cc_color_panel_set_calibrate_button_sensitivity:
+ **/
+static void
+cc_color_panel_set_calibrate_button_sensitivity (CcColorPanel *panel)
+{
+ gboolean ret = FALSE;
+ GtkWidget *widget;
+ const gchar *tooltip;
+ GcmDeviceKind kind;
+ gboolean connected;
+ gboolean xrandr_fallback;
+ gboolean has_vte = TRUE;
+
+ /* TRANSLATORS: this is when the button is sensitive */
+ tooltip = _("Create a color profile for the selected device");
+
+ /* no device selected */
+ if (panel->priv->current_device == NULL) {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("Cannot create profile: No device is selected");
+ goto out;
+ }
+
+#ifndef HAVE_VTE
+ has_vte = FALSE;
+#endif
+
+ /* no VTE support */
+ if (!has_vte) {
+ /* TRANSLATORS: this is when the button is insensitive because the distro compiled GCM without VTE */
+ tooltip = _("Cannot create profile: Virtual console support is missing");
+ goto out;
+ }
+
+ /* are we a display */
+ kind = gcm_device_get_kind (panel->priv->current_device);
+ if (kind == GCM_DEVICE_KIND_DISPLAY) {
+
+ /* are we disconnected */
+ connected = gcm_device_get_connected (panel->priv->current_device);
+ if (!connected) {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("Cannot create profile: The display device is not connected");
+ goto out;
+ }
+
+ /* are we not XRandR 1.3 compat */
+ xrandr_fallback = gcm_device_xrandr_get_fallback (GCM_DEVICE_XRANDR (panel->priv->current_device));
+ if (xrandr_fallback) {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("Cannot create profile: The display driver does not support XRandR 1.3");
+ goto out;
+ }
+
+ /* find whether we have hardware installed */
+ ret = gcm_colorimeter_get_present (panel->priv->colorimeter);
+ if (!ret) {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("Cannot create profile: The measuring instrument is not plugged in");
+ goto out;
+ }
+ } else if (kind == GCM_DEVICE_KIND_SCANNER ||
+ kind == GCM_DEVICE_KIND_CAMERA) {
+
+ /* TODO: find out if we can scan using gnome-scan */
+ ret = TRUE;
+
+ } else if (kind == GCM_DEVICE_KIND_PRINTER) {
+
+ /* find whether we have hardware installed */
+ ret = gcm_colorimeter_get_present (panel->priv->colorimeter);
+ if (!ret) {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("Cannot create profile: The measuring instrument is not plugged in");
+ goto out;
+ }
+
+ /* find whether we have hardware installed */
+ ret = gcm_colorimeter_supports_printer (panel->priv->colorimeter);
+ if (!ret) {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("Cannot create profile: The measuring instrument does not support printer profiling");
+ goto out;
+ }
+
+ } else {
+
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("Cannot create a profile for this type of device");
+ }
+out:
+ /* control the tooltip and sensitivity of the button */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_calibrate"));
+ gtk_widget_set_tooltip_text (widget, tooltip);
+ gtk_widget_set_sensitive (widget, ret);
+}
+
+/**
+ * cc_color_panel_devices_treeview_clicked_cb:
+ **/
+static void
+cc_color_panel_devices_treeview_clicked_cb (GtkTreeSelection *selection, CcColorPanel *panel)
+{
+ guint i;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkWidget *widget;
+ gfloat localgamma;
+ gfloat brightness;
+ gfloat contrast;
+ gboolean connected;
+ gchar *id = NULL;
+ gboolean ret;
+ GcmDeviceKind kind;
+ const gchar *device_serial = NULL;
+ const gchar *device_model = NULL;
+ const gchar *device_manufacturer = NULL;
+ const gchar *eisa_id = NULL;
+ GPtrArray *profiles = NULL;
+ GcmProfile *profile;
+
+ /* This will only work in single or browse selection mode! */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ egg_debug ("no row selected");
+ goto out;
+ }
+
+ /* get id */
+ gtk_tree_model_get (model, &iter,
+ GCM_DEVICES_COLUMN_ID, &id,
+ -1);
+
+ /* we have a new device */
+ egg_debug ("selected device is: %s", id);
+ if (panel->priv->current_device != NULL) {
+ g_object_unref (panel->priv->current_device);
+ panel->priv->current_device = NULL;
+ }
+ panel->priv->current_device = gcm_client_get_device_by_id (panel->priv->gcm_client, id);
+ if (panel->priv->current_device == NULL)
+ goto out;
+
+ /* not a xrandr device */
+ kind = gcm_device_get_kind (panel->priv->current_device);
+ if (kind != GCM_DEVICE_KIND_DISPLAY) {
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "expander_fine_tuning"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_reset"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ } else {
+ /* show more UI */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "expander_fine_tuning"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_reset"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ }
+
+ /* show broken devices */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "label_problems"));
+ if (kind == GCM_DEVICE_KIND_DISPLAY) {
+ ret = gcm_device_xrandr_get_fallback (GCM_DEVICE_XRANDR (panel->priv->current_device));
+ if (ret) {
+ /* TRANSLATORS: Some shitty binary drivers do not support per-head gamma controls.
+ * Whilst this does not matter if you only have one monitor attached, it means you
+ * can't color correct additional monitors or projectors. */
+ gtk_label_set_label (GTK_LABEL (widget), _("Per-device settings not supported. Check your display driver."));
+ gtk_widget_show (widget);
+ } else {
+ gtk_widget_hide (widget);
+ }
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ /* set device labels */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hbox_serial"));
+ device_serial = gcm_device_get_serial (panel->priv->current_device);
+ if (device_serial != NULL) {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "label_serial"));
+ gtk_label_set_label (GTK_LABEL (widget), device_serial);
+ } else {
+ gtk_widget_hide (widget);
+ }
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hbox_model"));
+ device_model = gcm_device_get_model (panel->priv->current_device);
+ if (device_model != NULL) {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "label_model"));
+ gtk_label_set_label (GTK_LABEL (widget), device_model);
+ } else {
+ gtk_widget_hide (widget);
+ }
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hbox_manufacturer"));
+ device_manufacturer = gcm_device_get_manufacturer (panel->priv->current_device);
+ if (device_manufacturer != NULL) {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "label_manufacturer"));
+ gtk_label_set_label (GTK_LABEL (widget), device_manufacturer);
+ } else {
+ gtk_widget_hide (widget);
+ }
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "vbox_device_details"));
+ gtk_widget_show (widget);
+
+ /* get display specific properties */
+ if (kind == GCM_DEVICE_KIND_DISPLAY)
+ eisa_id = gcm_device_xrandr_get_eisa_id (GCM_DEVICE_XRANDR (panel->priv->current_device));
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hbox_eisa"));
+ if (eisa_id != NULL) {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "label_eisa"));
+ gtk_label_set_label (GTK_LABEL (widget), eisa_id);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ /* set adjustments */
+ panel->priv->setting_up_device = TRUE;
+ localgamma = gcm_device_get_gamma (panel->priv->current_device);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_gamma"));
+ gtk_range_set_value (GTK_RANGE (widget), localgamma);
+ brightness = gcm_device_get_brightness (panel->priv->current_device);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_brightness"));
+ gtk_range_set_value (GTK_RANGE (widget), brightness);
+ contrast = gcm_device_get_contrast (panel->priv->current_device);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_contrast"));
+ gtk_range_set_value (GTK_RANGE (widget), contrast);
+ panel->priv->setting_up_device = FALSE;
+
+ /* clear existing list */
+ gtk_list_store_clear (panel->priv->list_store_assign);
+
+ /* add profiles for the device */
+ profiles = gcm_device_get_profiles (panel->priv->current_device);
+ for (i=0; i<profiles->len; i++) {
+ profile = g_ptr_array_index (profiles, i);
+ gtk_list_store_append (panel->priv->list_store_assign, &iter);
+ gtk_list_store_set (panel->priv->list_store_assign, &iter,
+ GCM_ASSIGN_COLUMN_PROFILE, profile,
+ GCM_ASSIGN_COLUMN_SORT, (i == 0) ? "0" : "1",
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, (i == 0),
+ -1);
+ }
+
+ /* select the default profile to display */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_assign"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ path = gtk_tree_path_new_from_string ("0");
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+
+ /* make sure selectable */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_profile"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_reset"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "label_profile"));
+ gtk_widget_set_sensitive (widget, TRUE);
+
+ /* can we delete this device? */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_delete"));
+ connected = gcm_device_get_connected (panel->priv->current_device);
+ gtk_widget_set_sensitive (widget, !connected);
+
+ /* can this device calibrate */
+ cc_color_panel_set_calibrate_button_sensitivity (panel);
+out:
+ if (profiles != NULL)
+ g_ptr_array_unref (profiles);
+ g_free (id);
+}
+
+/**
+ * cc_color_panel_assign_treeview_row_activated_cb:
+ **/
+static void
+cc_color_panel_assign_treeview_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
+ GtkTreeViewColumn *column, CcColorPanel *panel)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean ret;
+
+ /* get the iter */
+ model = GTK_TREE_MODEL (panel->priv->list_store_assign);
+ ret = gtk_tree_model_get_iter (model, &iter, path);
+ if (!ret)
+ return;
+
+ /* make this profile the default */
+ cc_color_panel_assign_make_default_internal (panel, model, &iter);
+}
+
+/**
+ * cc_color_panel_assign_treeview_clicked_cb:
+ **/
+static void
+cc_color_panel_assign_treeview_clicked_cb (GtkTreeSelection *selection, CcColorPanel *panel)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean is_default;
+ GtkWidget *widget;
+ GcmProfile *profile;
+
+ /* This will only work in single or browse selection mode! */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_make_default"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_remove"));
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ egg_debug ("no row selected");
+ return;
+ }
+
+ /* get profile */
+ gtk_tree_model_get (model, &iter,
+ GCM_ASSIGN_COLUMN_PROFILE, &profile,
+ GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+ -1);
+ egg_debug ("selected profile = %s", gcm_profile_get_filename (profile));
+
+ /* is the element the first in the list */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_make_default"));
+ gtk_widget_set_sensitive (widget, !is_default);
+
+ /* we can remove it now */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_remove"));
+ gtk_widget_set_sensitive (widget, TRUE);
+
+ /* show a warning if the profile is crap */
+ if (gcm_device_get_kind (panel->priv->current_device) == GCM_DEVICE_KIND_DISPLAY &&
+ !gcm_profile_get_has_vcgt (profile)) {
+ gtk_widget_show (panel->priv->info_bar_vcgt);
+ } else {
+ gtk_widget_hide (panel->priv->info_bar_vcgt);
+ }
+}
+
+/**
+ * gcm_device_kind_to_string:
+ **/
+static const gchar *
+cc_color_panel_device_kind_to_string (GcmDeviceKind kind)
+{
+ if (kind == GCM_DEVICE_KIND_DISPLAY)
+ return "1";
+ if (kind == GCM_DEVICE_KIND_SCANNER)
+ return "2";
+ if (kind == GCM_DEVICE_KIND_CAMERA)
+ return "3";
+ if (kind == GCM_DEVICE_KIND_PRINTER)
+ return "4";
+ return "5";
+}
+
+/**
+ * cc_color_panel_add_device_xrandr:
+ **/
+static void
+cc_color_panel_add_device_xrandr (CcColorPanel *panel, GcmDevice *device)
+{
+ GtkTreeIter iter;
+ const gchar *title_tmp;
+ gchar *title = NULL;
+ gchar *sort = NULL;
+ const gchar *id;
+ gboolean ret;
+ gboolean connected;
+ GError *error = NULL;
+
+ /* sanity check */
+ if (!GCM_IS_DEVICE_XRANDR (device)) {
+ egg_warning ("not a xrandr device");
+ goto out;
+ }
+
+ /* italic for non-connected devices */
+ connected = gcm_device_get_connected (device);
+ title_tmp = gcm_device_get_title (device);
+ if (connected) {
+ /* set the gamma on the device */
+ ret = gcm_device_apply (device, &error);
+ if (!ret) {
+ egg_warning ("failed to apply profile: %s", error->message);
+ g_error_free (error);
+ }
+
+ /* use a different title if we have crap xorg drivers */
+ if (ret) {
+ title = g_strdup (title_tmp);
+ } else {
+ /* TRANSLATORS: this is where an output is not settable, but we are showing it in the UI */
+ title = g_strdup_printf ("%s\n(%s)", title_tmp, _("No hardware support"));
+ }
+ } else {
+ /* TRANSLATORS: this is where the device has been setup but is not connected */
+ title = g_strdup_printf ("%s\n<i>[%s]</i>", title_tmp, _("disconnected"));
+ }
+
+ /* create sort order */
+ sort = g_strdup_printf ("%s%s",
+ cc_color_panel_device_kind_to_string (GCM_DEVICE_KIND_DISPLAY),
+ title);
+
+ /* add to list */
+ id = gcm_device_get_id (device);
+ egg_debug ("add %s to device list", id);
+ gtk_list_store_append (panel->priv->list_store_devices, &iter);
+ gtk_list_store_set (panel->priv->list_store_devices, &iter,
+ GCM_DEVICES_COLUMN_ID, id,
+ GCM_DEVICES_COLUMN_SORT, sort,
+ GCM_DEVICES_COLUMN_TITLE, title,
+ GCM_DEVICES_COLUMN_ICON, "video-display", -1);
+out:
+ g_free (sort);
+ g_free (title);
+}
+
+/**
+ * cc_color_panel_set_combo_simple_text:
+ **/
+static void
+cc_color_panel_set_combo_simple_text (GtkWidget *combo_box)
+{
+ GtkCellRenderer *renderer;
+ GtkListStore *store;
+
+ store = gtk_list_store_new (4, G_TYPE_STRING, GCM_TYPE_PROFILE, G_TYPE_UINT, G_TYPE_STRING);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), GCM_PREFS_COMBO_COLUMN_SORTABLE, GTK_SORT_ASCENDING);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "wrap-mode", PANGO_WRAP_WORD_CHAR,
+ "width-chars", 60,
+ NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
+ "text", GCM_PREFS_COMBO_COLUMN_TEXT,
+ NULL);
+}
+
+/**
+ * cc_color_panel_profile_combo_changed_cb:
+ **/
+static void
+cc_color_panel_profile_combo_changed_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ GFile *file = NULL;
+ GFile *dest = NULL;
+ gboolean ret;
+ GError *error = NULL;
+ GcmProfile *profile = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GcmPrefsEntryType entry_type;
+
+ /* no devices */
+ if (panel->priv->current_device == NULL)
+ return;
+
+ /* no selection */
+ ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
+ if (!ret)
+ return;
+
+ /* get entry */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_TYPE, &entry_type,
+ -1);
+
+ /* import */
+ if (entry_type == GCM_PREFS_ENTRY_TYPE_IMPORT) {
+ file = cc_color_panel_file_chooser_get_icc_profile (panel);
+ if (file == NULL) {
+ egg_warning ("failed to get ICC file");
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ goto out;
+ }
+
+ /* import this */
+ ret = cc_color_panel_profile_import_file (panel, file);
+ if (!ret) {
+ gchar *uri;
+ /* set to 'None' */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
+ uri = g_file_get_uri (file);
+ egg_debug ("%s did not import correctly", uri);
+ g_free (uri);
+ goto out;
+ }
+
+ /* get an object of the destination */
+ dest = gcm_utils_get_profile_destination (file);
+ profile = gcm_profile_new ();
+ ret = gcm_profile_parse (profile, dest, &error);
+ if (!ret) {
+ /* set to first entry */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ egg_warning ("failed to parse ICC file: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* check the file is suitable */
+ ret = cc_color_panel_is_profile_suitable_for_device (profile, panel->priv->current_device);
+ if (!ret) {
+ /* set to 'None' */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
+ /* TRANSLATORS: the profile was of the wrong sort for this device */
+ cc_color_panel_error_dialog (panel, _("Could not import profile"),
+ _("The profile was of the wrong type for this device"));
+ goto out;
+ }
+
+ /* add to combobox */
+ gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE(model), &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
+ GCM_PREFS_COMBO_COLUMN_SORTABLE, "0",
+ -1);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
+ }
+out:
+ if (file != NULL)
+ g_object_unref (file);
+ if (dest != NULL)
+ g_object_unref (dest);
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+/**
+ * cc_color_panel_slider_changed_cb:
+ **/
+static void
+cc_color_panel_slider_changed_cb (GtkRange *range, CcColorPanel *panel)
+{
+ gfloat localgamma;
+ gfloat brightness;
+ gfloat contrast;
+ GtkWidget *widget;
+ gboolean ret;
+ GError *error = NULL;
+
+ /* we're just setting up the device, not moving the slider */
+ if (panel->priv->setting_up_device)
+ return;
+
+ /* get values */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_gamma"));
+ localgamma = gtk_range_get_value (GTK_RANGE (widget));
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_brightness"));
+ brightness = gtk_range_get_value (GTK_RANGE (widget));
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_contrast"));
+ contrast = gtk_range_get_value (GTK_RANGE (widget));
+
+ gcm_device_set_gamma (panel->priv->current_device, localgamma);
+ gcm_device_set_brightness (panel->priv->current_device, brightness * 100.0f);
+ gcm_device_set_contrast (panel->priv->current_device, contrast * 100.0f);
+
+ /* save new profile */
+ ret = gcm_device_save (panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to save config: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* actually set the new profile */
+ ret = gcm_device_apply (panel->priv->current_device, &error);
+ if (!ret) {
+ egg_warning ("failed to apply profile: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
+}
+
+/**
+ * cc_color_panel_colorimeter_changed_cb:
+ **/
+static void
+cc_color_panel_colorimeter_changed_cb (GcmColorimeter *colorimeter, CcColorPanel *panel)
+{
+ gboolean present;
+ const gchar *event_id;
+ const gchar *message;
+
+ present = gcm_colorimeter_get_present (colorimeter);
+
+ if (present) {
+ /* TRANSLATORS: this is a sound description */
+ message = _("Device added");
+ event_id = "device-added";
+ } else {
+ /* TRANSLATORS: this is a sound description */
+ message = _("Device removed");
+ event_id = "device-removed";
+ }
+
+ /* play sound from the naming spec */
+ ca_context_play (ca_gtk_context_get (), 0,
+ CA_PROP_EVENT_ID, event_id,
+ /* TRANSLATORS: this is the application name for libcanberra */
+ CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
+ CA_PROP_EVENT_DESCRIPTION, message, NULL);
+
+ cc_color_panel_set_calibrate_button_sensitivity (panel);
+}
+
+/**
+ * cc_color_panel_device_kind_to_icon_name:
+ **/
+static const gchar *
+cc_color_panel_device_kind_to_icon_name (GcmDeviceKind kind)
+{
+ if (kind == GCM_DEVICE_KIND_DISPLAY)
+ return "video-display";
+ if (kind == GCM_DEVICE_KIND_SCANNER)
+ return "scanner";
+ if (kind == GCM_DEVICE_KIND_PRINTER)
+ return "printer";
+ if (kind == GCM_DEVICE_KIND_CAMERA)
+ return "camera-photo";
+ return "image-missing";
+}
+
+/**
+ * cc_color_panel_add_device_kind:
+ **/
+static void
+cc_color_panel_add_device_kind (CcColorPanel *panel, GcmDevice *device)
+{
+ GtkTreeIter iter;
+ const gchar *title;
+ GString *string;
+ const gchar *id;
+ gchar *sort = NULL;
+ GcmDeviceKind kind;
+ const gchar *icon_name;
+ gboolean connected;
+ gboolean virtual;
+
+ /* get icon */
+ kind = gcm_device_get_kind (device);
+ icon_name = cc_color_panel_device_kind_to_icon_name (kind);
+
+ /* create a title for the device */
+ title = gcm_device_get_title (device);
+ string = g_string_new (title);
+
+ /* italic for non-connected devices */
+ connected = gcm_device_get_connected (device);
+ virtual = gcm_device_get_virtual (device);
+ if (!connected && !virtual) {
+ /* TRANSLATORS: this is where the device has been setup but is not connected */
+ g_string_append_printf (string, "\n<i>[%s]</i>", _("disconnected"));
+ }
+
+ /* create sort order */
+ sort = g_strdup_printf ("%s%s",
+ cc_color_panel_device_kind_to_string (kind),
+ string->str);
+
+ /* add to list */
+ id = gcm_device_get_id (device);
+ gtk_list_store_append (panel->priv->list_store_devices, &iter);
+ gtk_list_store_set (panel->priv->list_store_devices, &iter,
+ GCM_DEVICES_COLUMN_ID, id,
+ GCM_DEVICES_COLUMN_SORT, sort,
+ GCM_DEVICES_COLUMN_TITLE, string->str,
+ GCM_DEVICES_COLUMN_ICON, icon_name, -1);
+ g_free (sort);
+ g_string_free (string, TRUE);
+}
+
+/**
+ * cc_color_panel_remove_device:
+ **/
+static void
+cc_color_panel_remove_device (CcColorPanel *panel, GcmDevice *gcm_device)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ const gchar *id;
+ gchar *id_tmp;
+ gboolean ret;
+
+ /* remove */
+ id = gcm_device_get_id (gcm_device);
+ egg_debug ("removing: %s (connected: %i)", id,
+ gcm_device_get_connected (gcm_device));
+
+ /* get first element */
+ model = GTK_TREE_MODEL (panel->priv->list_store_devices);
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ if (!ret)
+ return;
+
+ /* get the other elements */
+ do {
+ gtk_tree_model_get (model, &iter,
+ GCM_DEVICES_COLUMN_ID, &id_tmp,
+ -1);
+ if (g_strcmp0 (id_tmp, id) == 0) {
+ gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
+ g_free (id_tmp);
+ break;
+ }
+ g_free (id_tmp);
+ } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+/**
+ * cc_color_panel_added_cb:
+ **/
+static void
+cc_color_panel_added_cb (GcmClient *client, GcmDevice *device, CcColorPanel *panel)
+{
+ GcmDeviceKind kind;
+ egg_debug ("added: %s (connected: %i, saved: %i)",
+ gcm_device_get_id (device),
+ gcm_device_get_connected (device),
+ gcm_device_get_saved (device));
+
+ /* remove the saved device if it's already there */
+ cc_color_panel_remove_device (panel, device);
+
+ /* add the device */
+ kind = gcm_device_get_kind (device);
+ if (kind == GCM_DEVICE_KIND_DISPLAY)
+ cc_color_panel_add_device_xrandr (panel, device);
+ else
+ cc_color_panel_add_device_kind (panel, device);
+}
+
+/**
+ * cc_color_panel_changed_cb:
+ **/
+static void
+cc_color_panel_changed_cb (GcmClient *client, GcmDevice *device, CcColorPanel *panel)
+{
+ GcmDeviceKind kind;
+
+ /* no not re-add to the ui if we just deleted this */
+ if (!gcm_device_get_connected (device) &&
+ !gcm_device_get_saved (device)) {
+ egg_warning ("ignoring uninteresting device: %s", gcm_device_get_id (device));
+ return;
+ }
+
+ egg_debug ("changed: %s", gcm_device_get_id (device));
+
+ /* remove the saved device if it's already there */
+ cc_color_panel_remove_device (panel, device);
+
+ /* add the device */
+ kind = gcm_device_get_kind (device);
+ if (kind == GCM_DEVICE_KIND_DISPLAY)
+ cc_color_panel_add_device_xrandr (panel, device);
+ else
+ cc_color_panel_add_device_kind (panel, device);
+}
+
+/**
+ * cc_color_panel_removed_cb:
+ **/
+static void
+cc_color_panel_removed_cb (GcmClient *client, GcmDevice *device, CcColorPanel *panel)
+{
+ gboolean connected;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+ GtkWidget *widget;
+ gboolean ret;
+
+ /* remove from the UI */
+ cc_color_panel_remove_device (panel, device);
+
+ /* ensure this device is re-added if it's been saved */
+ connected = gcm_device_get_connected (device);
+ if (connected)
+ gcm_client_coldplug (panel->priv->gcm_client, GCM_CLIENT_COLDPLUG_SAVED, NULL);
+
+ /* select the first device */
+ ret = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (panel->priv->list_store_devices), &iter);
+ if (!ret)
+ return;
+
+ /* click it */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_devices"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget), GTK_TREE_MODEL (panel->priv->list_store_devices));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ gtk_tree_selection_select_iter (selection, &iter);
+}
+
+/**
+ * cc_color_panel_setup_space_combobox:
+ **/
+static void
+cc_color_panel_setup_space_combobox (CcColorPanel *panel, GtkWidget *widget, GcmColorspace colorspace, const gchar *profile_filename)
+{
+ GcmProfile *profile;
+ guint i;
+ const gchar *filename;
+ GcmColorspace colorspace_tmp;
+ gboolean has_profile = FALSE;
+ gboolean has_vcgt;
+ gboolean has_colorspace_description;
+ gchar *text = NULL;
+ GPtrArray *profile_array = NULL;
+ GtkTreeIter iter;
+
+ /* get new list */
+ profile_array = gcm_profile_store_get_array (panel->priv->profile_store);
+
+ /* update each list */
+ for (i=0; i<profile_array->len; i++) {
+ profile = g_ptr_array_index (profile_array, i);
+
+ /* only for correct kind */
+ has_vcgt = gcm_profile_get_has_vcgt (profile);
+ has_colorspace_description = gcm_profile_has_colorspace_description (profile);
+ colorspace_tmp = gcm_profile_get_colorspace (profile);
+ if (!has_vcgt &&
+ colorspace == colorspace_tmp &&
+ (colorspace == GCM_COLORSPACE_CMYK ||
+ has_colorspace_description)) {
+ cc_color_panel_combobox_add_profile (widget, profile, GCM_PREFS_ENTRY_TYPE_PROFILE, &iter);
+
+ /* set active option */
+ filename = gcm_profile_get_filename (profile);
+ if (g_strcmp0 (filename, profile_filename) == 0)
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
+ has_profile = TRUE;
+ }
+ }
+ if (!has_profile) {
+ /* TRANSLATORS: this is when there are no profiles that can be used; the search term is either "RGB" or "CMYK" */
+ text = g_strdup_printf (_("No %s color spaces available"),
+ gcm_colorspace_to_localised_string (colorspace));
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), text);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+ if (profile_array != NULL)
+ g_ptr_array_unref (profile_array);
+ g_free (text);
+}
+
+/**
+ * cc_color_panel_space_combo_changed_cb:
+ **/
+static void
+cc_color_panel_space_combo_changed_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ gboolean ret;
+ GtkTreeIter iter;
+ const gchar *filename;
+ GtkTreeModel *model;
+ GcmProfile *profile = NULL;
+ const gchar *key = g_object_get_data (G_OBJECT(widget), "GCM:GSettingsKey");
+
+ /* no selection */
+ ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
+ if (!ret)
+ return;
+
+ /* get profile */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+ -1);
+ if (profile == NULL)
+ goto out;
+
+ filename = gcm_profile_get_filename (profile);
+ egg_debug ("changed working space %s", filename);
+ g_settings_set_string (panel->priv->settings, key, filename);
+out:
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+/**
+ * cc_color_panel_renderer_combo_changed_cb:
+ **/
+static void
+cc_color_panel_renderer_combo_changed_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ gint active;
+ const gchar *key = g_object_get_data (G_OBJECT(widget), "GCM:GSettingsKey");
+
+ /* no selection */
+ active = gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+ if (active == -1)
+ return;
+
+ /* save to GSettings */
+ egg_debug ("changed rendering intent to %s", gcm_intent_to_string (active+1));
+ g_settings_set_enum (panel->priv->settings, key, active+1);
+}
+
+/**
+ * cc_color_panel_setup_rendering_combobox:
+ **/
+static void
+cc_color_panel_setup_rendering_combobox (GtkWidget *widget, GcmIntent intent)
+{
+ guint i;
+ gboolean ret = FALSE;
+ gchar *label;
+
+ for (i=1; i<GCM_INTENT_LAST; i++) {
+ label = g_strdup_printf ("%s - %s",
+ gcm_intent_to_localized_text (i),
+ gcm_intent_to_localized_description (i));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (widget), label);
+ g_free (label);
+ if (i == intent) {
+ ret = TRUE;
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), i-1);
+ }
+ }
+ /* nothing matches, just set the first option */
+ if (!ret)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+}
+
+/**
+ * cc_color_panel_startup_idle_cb:
+ **/
+static gboolean
+cc_color_panel_startup_idle_cb (CcColorPanel *panel)
+{
+ GtkWidget *widget;
+ gboolean ret;
+ GError *error = NULL;
+ gchar *colorspace_rgb;
+ gchar *colorspace_cmyk;
+ gint intent_display = -1;
+ gint intent_softproof = -1;
+
+ /* search the disk for profiles */
+ gcm_profile_store_search_default (panel->priv->profile_store);
+ g_signal_connect (panel->priv->profile_store, "changed", G_CALLBACK(cc_color_panel_profile_store_changed_cb), panel);
+
+ /* setup RGB combobox */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_space_rgb"));
+ colorspace_rgb = g_settings_get_string (panel->priv->settings, GCM_SETTINGS_COLORSPACE_RGB);
+ cc_color_panel_set_combo_simple_text (widget);
+ cc_color_panel_setup_space_combobox (panel, widget, GCM_COLORSPACE_RGB, colorspace_rgb);
+ g_object_set_data (G_OBJECT(widget), "GCM:GSettingsKey", (gpointer) GCM_SETTINGS_COLORSPACE_RGB);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ G_CALLBACK (cc_color_panel_space_combo_changed_cb), panel);
+
+ /* setup CMYK combobox */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_space_cmyk"));
+ colorspace_cmyk = g_settings_get_string (panel->priv->settings, GCM_SETTINGS_COLORSPACE_CMYK);
+ cc_color_panel_set_combo_simple_text (widget);
+ cc_color_panel_setup_space_combobox (panel, widget, GCM_COLORSPACE_CMYK, colorspace_cmyk);
+ g_object_set_data (G_OBJECT(widget), "GCM:GSettingsKey", (gpointer) GCM_SETTINGS_COLORSPACE_CMYK);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ G_CALLBACK (cc_color_panel_space_combo_changed_cb), panel);
+
+ /* setup rendering lists */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_rendering_display"));
+ cc_color_panel_set_combo_simple_text (widget);
+ intent_display = g_settings_get_enum (panel->priv->settings, GCM_SETTINGS_RENDERING_INTENT_DISPLAY);
+ cc_color_panel_setup_rendering_combobox (widget, intent_display);
+ g_object_set_data (G_OBJECT(widget), "GCM:GSettingsKey", (gpointer) GCM_SETTINGS_RENDERING_INTENT_DISPLAY);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ G_CALLBACK (cc_color_panel_renderer_combo_changed_cb), panel);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_rendering_softproof"));
+ cc_color_panel_set_combo_simple_text (widget);
+ intent_softproof = g_settings_get_enum (panel->priv->settings, GCM_SETTINGS_RENDERING_INTENT_SOFTPROOF);
+ cc_color_panel_setup_rendering_combobox (widget, intent_softproof);
+ g_object_set_data (G_OBJECT(widget), "GCM:GSettingsKey", (gpointer) GCM_SETTINGS_RENDERING_INTENT_SOFTPROOF);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ G_CALLBACK (cc_color_panel_renderer_combo_changed_cb), panel);
+
+ /* coldplug plugged in devices */
+ ret = gcm_client_coldplug (panel->priv->gcm_client, GCM_CLIENT_COLDPLUG_ALL, &error);
+ if (!ret) {
+ egg_warning ("failed to add connected devices: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* set calibrate button sensitivity */
+ cc_color_panel_set_calibrate_button_sensitivity (panel);
+
+ /* we're probably showing now */
+ panel->priv->main_window = gtk_widget_get_toplevel (panel->priv->info_bar_loading);
+
+ /* do we show the shared-color-profiles-extra installer? */
+ egg_debug ("getting installed");
+ ret = gcm_utils_is_package_installed (GCM_PREFS_PACKAGE_NAME_COLOR_PROFILES_EXTRA);
+ gtk_widget_set_visible (panel->priv->info_bar_profiles, !ret);
+out:
+ g_free (colorspace_rgb);
+ g_free (colorspace_cmyk);
+ return FALSE;
+}
+
+/**
+ * cc_color_panel_reset_devices_idle_cb:
+ **/
+static gboolean
+cc_color_panel_reset_devices_idle_cb (CcColorPanel *panel)
+{
+ GPtrArray *array = NULL;
+ GcmDevice *device;
+ GError *error = NULL;
+ gboolean ret;
+ guint i;
+
+ /* set for each output */
+ array = gcm_client_get_devices (panel->priv->gcm_client);
+ for (i=0; i<array->len; i++) {
+ device = g_ptr_array_index (array, i);
+
+ /* set gamma for device */
+ ret = gcm_device_apply (device, &error);
+ if (!ret) {
+ egg_warning ("failed to set profile: %s", error->message);
+ g_error_free (error);
+ break;
+ }
+ }
+ g_ptr_array_unref (array);
+ return FALSE;
+}
+
+/**
+ * cc_color_panel_checkbutton_changed_cb:
+ **/
+static void
+cc_color_panel_checkbutton_changed_cb (GtkWidget *widget, CcColorPanel *panel)
+{
+ /* set the new setting */
+ g_idle_add ((GSourceFunc) cc_color_panel_reset_devices_idle_cb, panel);
+}
+
+/**
+ * cc_color_panel_setup_drag_and_drop:
+ **/
+static void
+cc_color_panel_setup_drag_and_drop (GtkWidget *widget)
+{
+ GtkTargetEntry entry;
+
+ /* setup a dummy entry */
+ entry.target = g_strdup ("text/plain");
+ entry.flags = GTK_TARGET_OTHER_APP;
+ entry.info = 0;
+
+ gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, &entry, 1, GDK_ACTION_MOVE | GDK_ACTION_COPY);
+ g_free (entry.target);
+}
+
+/**
+ * cc_color_panel_profile_store_changed_cb:
+ **/
+static void
+cc_color_panel_profile_store_changed_cb (GcmProfileStore *profile_store, CcColorPanel *panel)
+{
+ GtkTreeSelection *selection;
+ GtkWidget *widget;
+
+ /* re-get all the profiles for this device */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_devices"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ if (selection == NULL)
+ return;
+ g_signal_emit_by_name (selection, "changed", panel);
+}
+
+/**
+ * cc_color_panel_select_first_device_idle_cb:
+ **/
+static gboolean
+cc_color_panel_select_first_device_idle_cb (CcColorPanel *panel)
+{
+ GtkTreePath *path;
+ GtkWidget *widget;
+
+ /* set the cursor on the first device */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_devices"));
+ path = gtk_tree_path_new_from_string ("0");
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path, NULL, FALSE);
+ gtk_tree_path_free (path);
+
+ return FALSE;
+}
+
+/**
+ * cc_color_panel_client_notify_loading_cb:
+ **/
+static void
+cc_color_panel_client_notify_loading_cb (GcmClient *client, GParamSpec *pspec, CcColorPanel *panel)
+{
+ gboolean loading;
+
+ /*if loading show the bar */
+ loading = gcm_client_get_loading (client);
+ if (loading) {
+ gtk_widget_show (panel->priv->info_bar_loading);
+ return;
+ }
+
+ /* otherwise clear the loading widget */
+ gtk_widget_hide (panel->priv->info_bar_loading);
+
+ /* idle callback */
+ g_idle_add ((GSourceFunc) cc_color_panel_select_first_device_idle_cb, panel);
+}
+
+/**
+ * cc_color_panel_info_bar_response_cb:
+ **/
+static void
+cc_color_panel_info_bar_response_cb (GtkDialog *dialog, GtkResponseType response, CcColorPanel *panel)
+{
+ GtkWindow *window;
+ gboolean ret;
+
+ if (response == GTK_RESPONSE_HELP) {
+ /* open the help file in the right place */
+ gcm_gnome_help ("faq-missing-vcgt");
+
+ } else if (response == GTK_RESPONSE_APPLY) {
+ /* install the extra profiles */
+ window = GTK_WINDOW(panel->priv->main_window);
+ ret = gcm_utils_install_package (GCM_PREFS_PACKAGE_NAME_COLOR_PROFILES_EXTRA, window);
+ if (ret)
+ gtk_widget_hide (panel->priv->info_bar_profiles);
+ }
+}
+
+/**
+ * gcm_device_kind_to_localised_string:
+ **/
+static const gchar *
+gcm_device_kind_to_localised_string (GcmDeviceKind device_kind)
+{
+ if (device_kind == GCM_DEVICE_KIND_DISPLAY) {
+ /* TRANSLATORS: device type */
+ return _("Display");
+ }
+ if (device_kind == GCM_DEVICE_KIND_SCANNER) {
+ /* TRANSLATORS: device type */
+ return _("Scanner");
+ }
+ if (device_kind == GCM_DEVICE_KIND_PRINTER) {
+ /* TRANSLATORS: device type */
+ return _("Printer");
+ }
+ if (device_kind == GCM_DEVICE_KIND_CAMERA) {
+ /* TRANSLATORS: device type */
+ return _("Camera");
+ }
+ return NULL;
+}
+
+/**
+ * cc_color_panel_setup_virtual_combobox:
+ **/
+static void
+cc_color_panel_setup_virtual_combobox (GtkWidget *widget)
+{
+ guint i;
+ const gchar *text;
+
+ for (i=GCM_DEVICE_KIND_SCANNER; i<GCM_DEVICE_KIND_LAST; i++) {
+ text = gcm_device_kind_to_localised_string (i);
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), text);
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), GCM_DEVICE_KIND_PRINTER - 2);
+}
+
+/**
+ * gpk_update_viewer_notify_network_state_cb:
+ **/
+static void
+cc_color_panel_button_virtual_entry_changed_cb (GtkEntry *entry, GParamSpec *pspec, CcColorPanel *panel)
+{
+ const gchar *model;
+ const gchar *manufacturer;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_model"));
+ model = gtk_entry_get_text (GTK_ENTRY (widget));
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_manufacturer"));
+ manufacturer = gtk_entry_get_text (GTK_ENTRY (widget));
+
+ /* only set the add button sensitive if both sections have text */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_virtual_add"));
+ gtk_widget_set_sensitive (widget, (model != NULL && model[0] != '\0' && manufacturer != NULL && manufacturer[0] != '\0'));
+}
+
+static void
+cc_color_panel_class_init (CcColorPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ g_type_class_add_private (klass, sizeof (CcColorPanelPrivate));
+ object_class->finalize = cc_color_panel_finalize;
+}
+
+static void
+cc_color_panel_class_finalize (CcColorPanelClass *klass)
+{
+}
+
+static void
+cc_color_panel_finalize (GObject *object)
+{
+ CcColorPanel *panel = CC_COLOR_PANEL (object);
+
+ if (panel->priv->current_device != NULL)
+ g_object_unref (panel->priv->current_device);
+ if (panel->priv->colorimeter != NULL)
+ g_object_unref (panel->priv->colorimeter);
+ if (panel->priv->settings != NULL)
+ g_object_unref (panel->priv->settings);
+ if (panel->priv->builder != NULL)
+ g_object_unref (panel->priv->builder);
+ if (panel->priv->profile_store != NULL)
+ g_object_unref (panel->priv->profile_store);
+ if (panel->priv->gcm_client != NULL)
+ g_object_unref (panel->priv->gcm_client);
+
+ G_OBJECT_CLASS (cc_color_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_color_panel_init (CcColorPanel *panel)
+{
+ GtkWidget *widget;
+ GtkWidget *main_window;
+ GError *error = NULL;
+ gint retval;
+ GtkTreeSelection *selection;
+ GtkWidget *info_bar_loading_label;
+ GtkWidget *info_bar_vcgt_label;
+ GtkWidget *info_bar_profiles_label;
+
+ panel->priv = CC_COLOR_PREFS_GET_PRIVATE (panel);
+
+ /* setup defaults */
+ panel->priv->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
+
+ /* get UI */
+ panel->priv->builder = gtk_builder_new ();
+ retval = gtk_builder_add_from_file (panel->priv->builder, GCM_DATA "/gcm-prefs.ui", &error);
+ if (retval == 0) {
+ egg_error ("failed to load ui: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* reparent */
+ main_window = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_prefs"));
+ widget = gtk_dialog_get_content_area (GTK_DIALOG (main_window));
+ gtk_widget_reparent (widget, GTK_WIDGET (panel));
+
+ /* add application specific icons to search path */
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+ GCM_DATA G_DIR_SEPARATOR_S "icons");
+
+ /* maintain a list of profiles */
+ panel->priv->profile_store = gcm_profile_store_new ();
+
+ /* create list stores */
+ panel->priv->list_store_devices = gtk_list_store_new (GCM_DEVICES_COLUMN_LAST, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING);
+ panel->priv->list_store_assign = gtk_list_store_new (GCM_ASSIGN_COLUMN_LAST, G_TYPE_STRING, GCM_TYPE_PROFILE, G_TYPE_BOOLEAN);
+
+ /* assign buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_add"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_assign_add_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_remove"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_assign_remove_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_make_default"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_assign_make_default_cb), panel);
+
+ /* create device tree view */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_devices"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+ GTK_TREE_MODEL (panel->priv->list_store_devices));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (cc_color_panel_devices_treeview_clicked_cb), panel);
+
+ /* add columns to the tree view */
+ cc_color_panel_add_devices_columns (panel, GTK_TREE_VIEW (widget));
+ gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
+
+ /* create assign tree view */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "treeview_assign"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+ GTK_TREE_MODEL (panel->priv->list_store_assign));
+ g_signal_connect (GTK_TREE_VIEW (widget), "row-activated",
+ G_CALLBACK (cc_color_panel_assign_treeview_row_activated_cb), panel);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (cc_color_panel_assign_treeview_clicked_cb), panel);
+
+ /* add columns to the tree view */
+ cc_color_panel_add_assign_columns (panel, GTK_TREE_VIEW (widget));
+ gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
+ gtk_tree_view_set_reorderable (GTK_TREE_VIEW (widget), TRUE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_default"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_default_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_help"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_help_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_viewer"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_viewer_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_reset"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_reset_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_delete"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_delete_cb), panel);
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_device_add"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_device_add_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_calibrate"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_calibrate_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "expander_fine_tuning"));
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ /* hide widgets by default */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "vbox_device_details"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "label_profile"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hbox_manufacturer"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hbox_model"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hbox_serial"));
+ gtk_widget_hide (widget);
+
+ /* set up virtual dialog */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_virtual"));
+ g_signal_connect (widget, "delete-event",
+ G_CALLBACK (cc_color_panel_virtual_delete_event_cb), panel);
+ g_signal_connect (widget, "drag-data-received",
+ G_CALLBACK (cc_color_panel_virtual_drag_data_received_cb), panel);
+ cc_color_panel_setup_drag_and_drop (widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_virtual_add"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_button_virtual_add_cb), panel);
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_virtual_cancel"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_button_virtual_cancel_cb), panel);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_virtual_type"));
+ cc_color_panel_set_combo_simple_text (widget);
+ cc_color_panel_setup_virtual_combobox (widget);
+
+ /* set up assign dialog */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "dialog_assign"));
+ g_signal_connect (widget, "delete-event",
+ G_CALLBACK (cc_color_panel_assign_delete_event_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_cancel"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_button_assign_cancel_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "button_assign_ok"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_button_assign_ok_cb), panel);
+
+ /* disable the add button if nothing in either box */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_model"));
+ g_signal_connect (widget, "notify::text",
+ G_CALLBACK (cc_color_panel_button_virtual_entry_changed_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "entry_virtual_manufacturer"));
+ g_signal_connect (widget, "notify::text",
+ G_CALLBACK (cc_color_panel_button_virtual_entry_changed_cb), panel);
+
+ /* setup icc profiles list */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "combobox_profile"));
+ cc_color_panel_set_combo_simple_text (widget);
+ gtk_widget_set_sensitive (widget, FALSE);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ G_CALLBACK (cc_color_panel_profile_combo_changed_cb), panel);
+
+ /* set ranges */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_gamma"));
+ gtk_range_set_range (GTK_RANGE (widget), 0.1f, 5.0f);
+ gtk_scale_add_mark (GTK_SCALE (widget), 1.0f, GTK_POS_TOP, "");
+ gtk_scale_add_mark (GTK_SCALE (widget), 1.8f, GTK_POS_TOP, "");
+ gtk_scale_add_mark (GTK_SCALE (widget), 2.2f, GTK_POS_TOP, "");
+
+ /* set ranges */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_brightness"));
+ gtk_range_set_range (GTK_RANGE (widget), 0.0f, 0.9f);
+// gtk_scale_add_mark (GTK_SCALE (widget), 0.0f, GTK_POS_TOP, "");
+
+ /* set ranges */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_contrast"));
+ gtk_range_set_range (GTK_RANGE (widget), 0.1f, 1.0f);
+// gtk_scale_add_mark (GTK_SCALE (widget), 1.0f, GTK_POS_TOP, "");
+
+ /* use a device client array */
+ panel->priv->gcm_client = gcm_client_new ();
+ gcm_client_set_use_threads (panel->priv->gcm_client, TRUE);
+ g_signal_connect (panel->priv->gcm_client, "added", G_CALLBACK (cc_color_panel_added_cb), panel);
+ g_signal_connect (panel->priv->gcm_client, "removed", G_CALLBACK (cc_color_panel_removed_cb), panel);
+ g_signal_connect (panel->priv->gcm_client, "changed", G_CALLBACK (cc_color_panel_changed_cb), panel);
+ g_signal_connect (panel->priv->gcm_client, "notify::loading",
+ G_CALLBACK (cc_color_panel_client_notify_loading_cb), panel);
+
+ /* use the color device */
+ panel->priv->colorimeter = gcm_colorimeter_new ();
+ g_signal_connect (panel->priv->colorimeter, "changed", G_CALLBACK (cc_color_panel_colorimeter_changed_cb), panel);
+
+ /* use infobar */
+ panel->priv->info_bar_loading = gtk_info_bar_new ();
+ panel->priv->info_bar_vcgt = gtk_info_bar_new ();
+ g_signal_connect (panel->priv->info_bar_vcgt, "response",
+ G_CALLBACK (cc_color_panel_info_bar_response_cb), panel);
+ panel->priv->info_bar_profiles = gtk_info_bar_new ();
+ g_signal_connect (panel->priv->info_bar_profiles, "response",
+ G_CALLBACK (cc_color_panel_info_bar_response_cb), panel);
+
+ /* TRANSLATORS: button for more details about the vcgt failure */
+ gtk_info_bar_add_button (GTK_INFO_BAR(panel->priv->info_bar_vcgt), _("More Information"), GTK_RESPONSE_HELP);
+
+ /* TRANSLATORS: button to install extra profiles */
+ gtk_info_bar_add_button (GTK_INFO_BAR(panel->priv->info_bar_profiles), _("Install now"), GTK_RESPONSE_APPLY);
+
+ /* TRANSLATORS: this is displayed while the devices are being probed */
+ info_bar_loading_label = gtk_label_new (_("Loading list of devicesâ?¦"));
+ gtk_info_bar_set_message_type (GTK_INFO_BAR(panel->priv->info_bar_loading), GTK_MESSAGE_INFO);
+ widget = gtk_info_bar_get_content_area (GTK_INFO_BAR(panel->priv->info_bar_loading));
+ gtk_container_add (GTK_CONTAINER(widget), info_bar_loading_label);
+ gtk_widget_show (info_bar_loading_label);
+
+ /* TRANSLATORS: this is displayed when the profile is crap */
+ info_bar_vcgt_label = gtk_label_new (_("This profile does not have the information required for whole-screen color correction."));
+ gtk_label_set_line_wrap (GTK_LABEL (info_bar_vcgt_label), TRUE);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR(panel->priv->info_bar_vcgt), GTK_MESSAGE_INFO);
+ widget = gtk_info_bar_get_content_area (GTK_INFO_BAR(panel->priv->info_bar_vcgt));
+ gtk_container_add (GTK_CONTAINER(widget), info_bar_vcgt_label);
+ gtk_widget_show (info_bar_vcgt_label);
+
+ /* TRANSLATORS: this is displayed when the profile is crap */
+ info_bar_profiles_label = gtk_label_new (_("More color profiles could be automatically installed."));
+ gtk_label_set_line_wrap (GTK_LABEL (info_bar_profiles_label), TRUE);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR(panel->priv->info_bar_profiles), GTK_MESSAGE_INFO);
+ widget = gtk_info_bar_get_content_area (GTK_INFO_BAR(panel->priv->info_bar_profiles));
+ gtk_container_add (GTK_CONTAINER(widget), info_bar_profiles_label);
+ gtk_widget_show (info_bar_profiles_label);
+
+ /* add infobar to devices pane */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "vbox_devices"));
+ gtk_box_pack_start (GTK_BOX(widget), panel->priv->info_bar_loading, FALSE, FALSE, 0);
+
+ /* add infobar to devices pane */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "vbox_sections"));
+ gtk_box_pack_start (GTK_BOX(widget), panel->priv->info_bar_vcgt, FALSE, FALSE, 0);
+
+ /* add infobar to defaults pane */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "vbox3"));
+ gtk_box_pack_start (GTK_BOX(widget), panel->priv->info_bar_profiles, TRUE, FALSE, 0);
+
+ /* connect up sliders */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_contrast"));
+ g_signal_connect (widget, "value-changed",
+ G_CALLBACK (cc_color_panel_slider_changed_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_brightness"));
+ g_signal_connect (widget, "value-changed",
+ G_CALLBACK (cc_color_panel_slider_changed_cb), panel);
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "hscale_gamma"));
+ g_signal_connect (widget, "value-changed",
+ G_CALLBACK (cc_color_panel_slider_changed_cb), panel);
+
+ /* connect up global widget */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "checkbutton_display"));
+ g_settings_bind (panel->priv->settings,
+ GCM_SETTINGS_GLOBAL_DISPLAY_CORRECTION,
+ widget, "active",
+ G_SETTINGS_BIND_DEFAULT);
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_checkbutton_changed_cb), panel);
+
+ /* connect up atom widget */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "checkbutton_profile"));
+ g_settings_bind (panel->priv->settings,
+ GCM_SETTINGS_SET_ICC_PROFILE_ATOM,
+ widget, "active",
+ G_SETTINGS_BIND_DEFAULT);
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (cc_color_panel_checkbutton_changed_cb), panel);
+
+ /* do we show the fine tuning box */
+ widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "expander_fine_tuning"));
+ g_settings_bind (panel->priv->settings,
+ GCM_SETTINGS_SHOW_FINE_TUNING,
+ widget, "visible",
+ G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY);
+
+ /* get main window */
+ panel->priv->main_window = gtk_widget_get_toplevel (panel->priv->info_bar_loading);
+
+ /* connect up drags */
+ g_signal_connect (panel->priv->main_window, "drag-data-received",
+ G_CALLBACK (cc_color_panel_drag_data_received_cb), panel);
+if(0) cc_color_panel_setup_drag_and_drop (GTK_WIDGET (panel->priv->main_window));
+
+ /* do all this after the window has been set up */
+ g_idle_add ((GSourceFunc) cc_color_panel_startup_idle_cb, panel);
+out:
+ return;
+}
+
+void
+cc_color_panel_register (GIOModule *module)
+{
+ cc_color_panel_register_type (G_TYPE_MODULE (module));
+ g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT,
+ CC_TYPE_COLOR_PANEL,
+ "color", 0);
+}
+
+/* GIO extension stuff */
+void
+g_io_module_load (GIOModule *module)
+{
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ /* register the panel */
+ cc_color_panel_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
diff --git a/src/cc-color-panel.h b/src/cc-color-panel.h
new file mode 100644
index 0000000..c43b744
--- /dev/null
+++ b/src/cc-color-panel.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CC_COLOR_PANEL_H
+#define _CC_COLOR_PANEL_H
+
+#include <libgnome-control-center/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_COLOR_PANEL cc_color_panel_get_type()
+#define CC_COLOR_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_COLOR_PANEL, CcColorPanel))
+#define CC_COLOR_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_COLOR_PANEL, CcColorPanelClass))
+#define CC_IS_COLOR_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_COLOR_PANEL))
+#define CC_IS_COLOR_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_COLOR_PANEL))
+#define CC_COLOR_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_COLOR_PANEL, CcColorPanelClass))
+
+typedef struct _CcColorPanel CcColorPanel;
+typedef struct _CcColorPanelClass CcColorPanelClass;
+typedef struct _CcColorPanelPrivate CcColorPanelPrivate;
+
+struct _CcColorPanel {
+ CcPanel parent;
+ CcColorPanelPrivate *priv;
+};
+
+struct _CcColorPanelClass {
+ CcPanelClass parent_class;
+};
+
+GType cc_color_panel_get_type (void) G_GNUC_CONST;
+void cc_color_panel_register (GIOModule *module);
+
+G_END_DECLS
+
+#endif /* _CC_COLOR_PANEL_H */
diff --git a/src/gcm-viewer.c b/src/gcm-viewer.c
new file mode 100644
index 0000000..e65f039
--- /dev/null
+++ b/src/gcm-viewer.c
@@ -0,0 +1,1173 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009-2010 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glib/gstdio.h>
+#include <locale.h>
+#include <canberra-gtk.h>
+
+#include "egg-debug.h"
+
+#include "gcm-cell-renderer-profile.h"
+#include "gcm-calibrate-argyll.h"
+#include "gcm-cie-widget.h"
+#include "gcm-image.h"
+#include "gcm-profile.h"
+#include "gcm-profile-store.h"
+#include "gcm-trc-widget.h"
+#include "gcm-utils.h"
+#include "gcm-xyz.h"
+
+typedef struct {
+ GtkBuilder *builder;
+ GtkApplication *application;
+ GtkListStore *list_store_profiles;
+ GcmProfileStore *profile_store;
+ GtkWidget *cie_widget;
+ GtkWidget *trc_widget;
+ GtkWidget *vcgt_widget;
+ GtkWidget *preview_widget_input;
+ GtkWidget *preview_widget_output;
+ GSettings *settings;
+} GcmViewerPrivate;
+
+enum {
+ GCM_PROFILES_COLUMN_ID,
+ GCM_PROFILES_COLUMN_SORT,
+ GCM_PROFILES_COLUMN_ICON,
+ GCM_PROFILES_COLUMN_PROFILE,
+ GCM_PROFILES_COLUMN_LAST
+};
+
+enum {
+ GCM_VIEWER_COMBO_COLUMN_TEXT,
+ GCM_VIEWER_COMBO_COLUMN_PROFILE,
+ GCM_VIEWER_COMBO_COLUMN_TYPE,
+ GCM_VIEWER_COMBO_COLUMN_SORTABLE,
+ GCM_VIEWER_COMBO_COLUMN_LAST
+};
+
+static void gcm_viewer_profile_store_changed_cb (GcmProfileStore *profile_store, GcmViewerPrivate *viewer);
+
+#define GCM_VIEWER_TREEVIEW_WIDTH 350 /* px */
+
+/**
+ * gcm_viewer_error_dialog:
+ **/
+static void
+gcm_viewer_error_dialog (GcmViewerPrivate *viewer, const gchar *title, const gchar *message)
+{
+ GtkWindow *window;
+ GtkWidget *dialog;
+
+ window = GTK_WINDOW(gtk_builder_get_object (viewer->builder, "dialog_viewer"));
+ dialog = gtk_message_dialog_new (window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", title);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+/**
+ * gcm_viewer_close_cb:
+ **/
+static void
+gcm_viewer_close_cb (GtkWidget *widget, GcmViewerPrivate *viewer)
+{
+ gtk_application_quit (viewer->application);
+}
+
+/**
+ * gcm_viewer_preferences_cb:
+ **/
+static void
+gcm_viewer_preferences_cb (GtkWidget *widget, GcmViewerPrivate *viewer)
+{
+ gboolean ret;
+ GError *error = NULL;
+ ret = g_spawn_command_line_async ("gnome-control-center color", &error);
+ if (!ret) {
+ egg_warning ("failed to run prefs: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * gcm_viewer_help_cb:
+ **/
+static void
+gcm_viewer_help_cb (GtkWidget *widget, GcmViewerPrivate *viewer)
+{
+ gcm_gnome_help ("viewer");
+}
+
+/**
+ * gcm_viewer_delete_event_cb:
+ **/
+static gboolean
+gcm_viewer_delete_event_cb (GtkWidget *widget, GdkEvent *event, GcmViewerPrivate *viewer)
+{
+ gcm_viewer_close_cb (widget, viewer);
+ return FALSE;
+}
+
+/**
+ * gcm_viewer_profile_kind_to_icon_name:
+ **/
+static const gchar *
+gcm_viewer_profile_kind_to_icon_name (GcmProfileKind kind)
+{
+ if (kind == GCM_PROFILE_KIND_DISPLAY_DEVICE)
+ return "video-display";
+ if (kind == GCM_PROFILE_KIND_INPUT_DEVICE)
+ return "scanner";
+ if (kind == GCM_PROFILE_KIND_OUTPUT_DEVICE)
+ return "printer";
+ if (kind == GCM_PROFILE_KIND_COLORSPACE_CONVERSION)
+ return "view-refresh";
+ if (kind == GCM_PROFILE_KIND_ABSTRACT)
+ return "insert-link";
+ return "image-missing";
+}
+
+/**
+ * gcm_viewer_profile_get_sort_string:
+ **/
+static const gchar *
+gcm_viewer_profile_get_sort_string (GcmProfileKind kind)
+{
+ if (kind == GCM_PROFILE_KIND_DISPLAY_DEVICE)
+ return "1";
+ if (kind == GCM_PROFILE_KIND_INPUT_DEVICE)
+ return "2";
+ if (kind == GCM_PROFILE_KIND_OUTPUT_DEVICE)
+ return "3";
+ return "4";
+}
+
+/**
+ * gcm_viewer_update_profile_list:
+ **/
+static void
+gcm_viewer_update_profile_list (GcmViewerPrivate *viewer)
+{
+ GtkTreeIter iter;
+ const gchar *description;
+ const gchar *icon_name;
+ GcmProfileKind profile_kind = GCM_PROFILE_KIND_UNKNOWN;
+ GcmProfile *profile;
+ guint i;
+ const gchar *filename = NULL;
+ gchar *sort = NULL;
+ GPtrArray *profile_array = NULL;
+
+ egg_debug ("updating profile list");
+
+ /* get new list */
+ profile_array = gcm_profile_store_get_array (viewer->profile_store);
+
+ /* clear existing list */
+ gtk_list_store_clear (viewer->list_store_profiles);
+
+ /* update each list */
+ for (i=0; i<profile_array->len; i++) {
+ profile = g_ptr_array_index (profile_array, i);
+
+ profile_kind = gcm_profile_get_kind (profile);
+ icon_name = gcm_viewer_profile_kind_to_icon_name (profile_kind);
+ gtk_list_store_append (viewer->list_store_profiles, &iter);
+ description = gcm_profile_get_description (profile);
+ sort = g_strdup_printf ("%s%s",
+ gcm_viewer_profile_get_sort_string (profile_kind),
+ description);
+ filename = gcm_profile_get_filename (profile);
+ egg_debug ("add %s to profiles list", filename);
+ gtk_list_store_set (viewer->list_store_profiles, &iter,
+ GCM_PROFILES_COLUMN_ID, filename,
+ GCM_PROFILES_COLUMN_SORT, sort,
+ GCM_PROFILES_COLUMN_ICON, icon_name,
+ GCM_PROFILES_COLUMN_PROFILE, profile,
+ -1);
+
+ g_free (sort);
+ }
+ if (profile_array != NULL)
+ g_ptr_array_unref (profile_array);
+}
+
+/**
+ * gcm_viewer_profile_delete_cb:
+ **/
+static void
+gcm_viewer_profile_delete_cb (GtkWidget *widget, GcmViewerPrivate *viewer)
+{
+ GtkWidget *dialog;
+ GtkResponseType response;
+ GtkWindow *window;
+ gint retval;
+ const gchar *filename;
+ GcmProfile *profile;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ /* ask the user to confirm */
+ window = GTK_WINDOW(gtk_builder_get_object (viewer->builder, "dialog_viewer"));
+ dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL,
+ /* TRANSLATORS: title, usually we can tell based on the EDID data or output name */
+ _("Permanently delete profile?"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ /* TRANSLATORS: dialog message */
+ _("Are you sure you want to remove this profile from your system permanently?"));
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
+ /* TRANSLATORS: button, delete a profile */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Delete"), GTK_RESPONSE_YES);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ if (response != GTK_RESPONSE_YES)
+ goto out;
+
+ /* get the selected row */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "treeview_profiles"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ egg_debug ("no row selected");
+ goto out;
+ }
+
+ /* get profile */
+ gtk_tree_model_get (model, &iter,
+ GCM_PROFILES_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* try to remove file */
+ filename = gcm_profile_get_filename (profile);
+ retval = g_unlink (filename);
+ if (retval != 0)
+ goto out;
+out:
+ return;
+}
+
+/**
+ * gcm_viewer_file_chooser_get_icc_profile:
+ **/
+static GFile *
+gcm_viewer_file_chooser_get_icc_profile (GcmViewerPrivate *viewer)
+{
+ GtkWindow *window;
+ GtkWidget *dialog;
+ GFile *file = NULL;
+ GtkFileFilter *filter;
+
+ /* create new dialog */
+ window = GTK_WINDOW(gtk_builder_get_object (viewer->builder, "dialog_viewer"));
+ /* TRANSLATORS: dialog for file->open dialog */
+ dialog = gtk_file_chooser_dialog_new (_("Select ICC Profile File"), window,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Import"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(dialog), g_get_home_dir ());
+ gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER(dialog), FALSE);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER(dialog), FALSE);
+
+ /* setup the filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_mime_type (filter, "application/vnd.iccprofile");
+
+ /* we can remove this when we depend on a new shared-mime-info */
+ gtk_file_filter_add_pattern (filter, "*.icc");
+ gtk_file_filter_add_pattern (filter, "*.icm");
+ gtk_file_filter_add_pattern (filter, "*.ICC");
+ gtk_file_filter_add_pattern (filter, "*.ICM");
+
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("Supported ICC profiles"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* setup the all files filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* did user choose file */
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER(dialog));
+
+ /* we're done */
+ gtk_widget_destroy (dialog);
+
+ /* or NULL for missing */
+ return file;
+}
+
+/**
+ * gcm_viewer_profile_import_file:
+ **/
+static gboolean
+gcm_viewer_profile_import_file (GcmViewerPrivate *viewer, GFile *file)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GFile *destination = NULL;
+
+ /* check if correct type */
+ ret = gcm_utils_is_icc_profile (file);
+ if (!ret) {
+ egg_debug ("not a ICC profile");
+ goto out;
+ }
+
+ /* copy icc file to ~/.color/icc */
+ destination = gcm_utils_get_profile_destination (file);
+ ret = gcm_utils_mkdir_and_copy (file, destination, &error);
+ if (!ret) {
+ /* TRANSLATORS: could not read file */
+ gcm_viewer_error_dialog (viewer, _("Failed to copy file"), error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (destination != NULL)
+ g_object_unref (destination);
+ return ret;
+}
+
+/**
+ * gcm_viewer_profile_import_cb:
+ **/
+static void
+gcm_viewer_profile_import_cb (GtkWidget *widget, GcmViewerPrivate *viewer)
+{
+ GFile *file;
+
+ /* get new file */
+ file = gcm_viewer_file_chooser_get_icc_profile (viewer);
+ if (file == NULL) {
+ egg_warning ("failed to get filename");
+ goto out;
+ }
+
+ /* import this */
+ gcm_viewer_profile_import_file (viewer, file);
+out:
+ if (file != NULL)
+ g_object_unref (file);
+}
+
+/**
+ * gcm_viewer_drag_data_received_cb:
+ **/
+static void
+gcm_viewer_drag_data_received_cb (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint _time, GcmViewerPrivate *viewer)
+{
+ const guchar *filename;
+ gchar **filenames = NULL;
+ GFile *file = NULL;
+ guint i;
+ gboolean ret;
+ gboolean success = FALSE;
+
+ /* get filenames */
+ filename = gtk_selection_data_get_data (data);
+ if (filename == NULL)
+ goto out;
+
+ /* import this */
+ egg_debug ("dropped: %p (%s)", data, filename);
+
+ /* split, as multiple drag targets are accepted */
+ filenames = g_strsplit_set ((const gchar *)filename, "\r\n", -1);
+ for (i=0; filenames[i]!=NULL; i++) {
+
+ /* blank entry */
+ if (filenames[i][0] == '\0')
+ continue;
+
+ /* convert the URI */
+ file = g_file_new_for_uri (filenames[i]);
+
+ /* try to import it */
+ ret = gcm_viewer_profile_import_file (viewer, file);
+ if (ret)
+ success = TRUE;
+
+ g_object_unref (file);
+ }
+
+out:
+ gtk_drag_finish (context, success, FALSE, _time);
+ g_strfreev (filenames);
+}
+
+/**
+ * gcm_window_set_parent_xid:
+ **/
+static void
+gcm_window_set_parent_xid (GtkWindow *window, guint32 xid)
+{
+ GdkDisplay *display;
+ GdkWindow *parent_window;
+ GdkWindow *our_window;
+
+ display = gdk_display_get_default ();
+ parent_window = gdk_window_foreign_new_for_display (display, xid);
+ our_window = gtk_widget_get_window (GTK_WIDGET (window));
+ if (our_window == NULL) {
+ egg_warning ("failed to get our window");
+ return;
+ }
+
+ /* set this above our parent */
+ gtk_window_set_modal (window, TRUE);
+ gdk_window_set_transient_for (our_window, parent_window);
+}
+
+/**
+ * gcm_viewer_add_profiles_columns:
+ **/
+static void
+gcm_viewer_add_profiles_columns (GcmViewerPrivate *viewer, GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* image */
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DND, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("", renderer,
+ "icon-name", GCM_PROFILES_COLUMN_ICON, NULL);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* set minimum width */
+ gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_VIEWER_TREEVIEW_WIDTH, -1);
+
+ /* column for text */
+ renderer = gcm_cell_renderer_profile_new ();
+ g_object_set (renderer,
+ "wrap-mode", PANGO_WRAP_WORD,
+ "wrap-width", GCM_VIEWER_TREEVIEW_WIDTH - 62,
+ NULL);
+ column = gtk_tree_view_column_new_with_attributes ("", renderer,
+ "profile", GCM_PROFILES_COLUMN_PROFILE, NULL);
+ gtk_tree_view_column_set_sort_column_id (column, GCM_PROFILES_COLUMN_SORT);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (viewer->list_store_profiles), GCM_PROFILES_COLUMN_SORT, GTK_SORT_ASCENDING);
+ gtk_tree_view_append_column (treeview, column);
+ gtk_tree_view_column_set_expand (column, TRUE);
+}
+
+/**
+ * gcm_viewer_profile_kind_to_string:
+ **/
+static gchar *
+gcm_viewer_profile_kind_to_string (GcmProfileKind kind)
+{
+ if (kind == GCM_PROFILE_KIND_INPUT_DEVICE) {
+ /* TRANSLATORS: this the ICC profile type */
+ return _("Input device");
+ }
+ if (kind == GCM_PROFILE_KIND_DISPLAY_DEVICE) {
+ /* TRANSLATORS: this the ICC profile type */
+ return _("Display device");
+ }
+ if (kind == GCM_PROFILE_KIND_OUTPUT_DEVICE) {
+ /* TRANSLATORS: this the ICC profile type */
+ return _("Output device");
+ }
+ if (kind == GCM_PROFILE_KIND_DEVICELINK) {
+ /* TRANSLATORS: this the ICC profile type */
+ return _("Devicelink");
+ }
+ if (kind == GCM_PROFILE_KIND_COLORSPACE_CONVERSION) {
+ /* TRANSLATORS: this the ICC profile type */
+ return _("Colorspace conversion");
+ }
+ if (kind == GCM_PROFILE_KIND_ABSTRACT) {
+ /* TRANSLATORS: this the ICC profile kind */
+ return _("Abstract");
+ }
+ if (kind == GCM_PROFILE_KIND_NAMED_COLOR) {
+ /* TRANSLATORS: this the ICC profile type */
+ return _("Named color");
+ }
+ /* TRANSLATORS: this the ICC profile type */
+ return _("Unknown");
+}
+
+/**
+ * gcm_viewer_profile_colorspace_to_string:
+ **/
+static gchar *
+gcm_viewer_profile_colorspace_to_string (GcmColorspace colorspace)
+{
+ if (colorspace == GCM_COLORSPACE_XYZ) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("XYZ");
+ }
+ if (colorspace == GCM_COLORSPACE_LAB) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("LAB");
+ }
+ if (colorspace == GCM_COLORSPACE_LUV) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("LUV");
+ }
+ if (colorspace == GCM_COLORSPACE_YCBCR) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("YCbCr");
+ }
+ if (colorspace == GCM_COLORSPACE_YXY) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("Yxy");
+ }
+ if (colorspace == GCM_COLORSPACE_RGB) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("RGB");
+ }
+ if (colorspace == GCM_COLORSPACE_GRAY) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("Gray");
+ }
+ if (colorspace == GCM_COLORSPACE_HSV) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("HSV");
+ }
+ if (colorspace == GCM_COLORSPACE_CMYK) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("CMYK");
+ }
+ if (colorspace == GCM_COLORSPACE_CMY) {
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("CMY");
+ }
+ /* TRANSLATORS: this the ICC colorspace type */
+ return _("Unknown");
+}
+
+/**
+ * gcm_viewer_profiles_treeview_clicked_cb:
+ **/
+static void
+gcm_viewer_profiles_treeview_clicked_cb (GtkTreeSelection *selection, GcmViewerPrivate *viewer)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *widget;
+ GcmProfile *profile;
+ GcmClut *clut_trc = NULL;
+ GcmClut *clut_vcgt = NULL;
+ GcmXyz *white;
+ GcmXyz *red;
+ GcmXyz *green;
+ GcmXyz *blue;
+ const gchar *profile_copyright;
+ const gchar *profile_manufacturer;
+ const gchar *profile_model ;
+ const gchar *profile_datetime;
+ gchar *temp;
+ const gchar *filename;
+ gchar *basename = NULL;
+ gchar *size_text = NULL;
+ GcmProfileKind profile_kind;
+ GcmColorspace profile_colorspace;
+ const gchar *profile_kind_text;
+ const gchar *profile_colorspace_text;
+ gboolean ret;
+ gboolean has_vcgt;
+ guint size = 0;
+ guint filesize;
+ gfloat x;
+ gboolean show_section = FALSE;
+
+ /* This will only work in single or browse selection mode! */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ egg_debug ("no row selected");
+ return;
+ }
+
+ /* get profile */
+ gtk_tree_model_get (model, &iter,
+ GCM_PROFILES_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* set the preview widgets */
+ if (gcm_profile_get_colorspace (profile) == GCM_COLORSPACE_RGB) {
+ gcm_image_set_input_profile (GCM_IMAGE(viewer->preview_widget_input), profile);
+ gcm_image_set_abstract_profile (GCM_IMAGE(viewer->preview_widget_input), NULL);
+ gcm_image_set_output_profile (GCM_IMAGE(viewer->preview_widget_output), profile);
+ gcm_image_set_abstract_profile (GCM_IMAGE(viewer->preview_widget_output), NULL);
+ show_section = TRUE;
+ } else if (gcm_profile_get_colorspace (profile) == GCM_COLORSPACE_LAB) {
+ gcm_image_set_input_profile (GCM_IMAGE(viewer->preview_widget_input), NULL);
+ gcm_image_set_abstract_profile (GCM_IMAGE(viewer->preview_widget_input), profile);
+ gcm_image_set_output_profile (GCM_IMAGE(viewer->preview_widget_output), NULL);
+ gcm_image_set_abstract_profile (GCM_IMAGE(viewer->preview_widget_output), profile);
+ show_section = TRUE;
+ } else {
+ gcm_image_set_input_profile (GCM_IMAGE(viewer->preview_widget_input), NULL);
+ gcm_image_set_abstract_profile (GCM_IMAGE(viewer->preview_widget_input), NULL);
+ gcm_image_set_output_profile (GCM_IMAGE(viewer->preview_widget_output), NULL);
+ gcm_image_set_abstract_profile (GCM_IMAGE(viewer->preview_widget_output), NULL);
+ }
+
+ /* get the new details from the profile */
+ g_object_get (profile,
+ "white", &white,
+ "red", &red,
+ "green", &green,
+ "blue", &blue,
+ NULL);
+
+ /* check we have enough data for the CIE widget */
+ x = gcm_xyz_get_x (red);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_cie_axis"));
+ if (x > 0.001) {
+ g_object_set (viewer->cie_widget,
+ "white", white,
+ "red", red,
+ "green", green,
+ "blue", blue,
+ NULL);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ /* get curve data */
+ clut_trc = gcm_profile_generate_curve (profile, 256);
+
+ /* only show if there is useful information */
+ if (clut_trc != NULL)
+ size = gcm_clut_get_size (clut_trc);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_trc_axis"));
+ if (size > 0) {
+ g_object_set (viewer->trc_widget,
+ "clut", clut_trc,
+ NULL);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ /* get vcgt data */
+ clut_vcgt = gcm_profile_generate_vcgt (profile, 256);
+
+ /* only show if there is useful information */
+ if (clut_vcgt != NULL)
+ size = gcm_clut_get_size (clut_vcgt);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_vcgt_axis"));
+ if (size > 0) {
+ g_object_set (viewer->vcgt_widget,
+ "clut", clut_vcgt,
+ NULL);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ /* set kind */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_type"));
+ profile_kind = gcm_profile_get_kind (profile);
+ if (profile_kind == GCM_PROFILE_KIND_UNKNOWN) {
+ gtk_widget_hide (widget);
+ } else {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_type"));
+ profile_kind_text = gcm_viewer_profile_kind_to_string (profile_kind);
+ gtk_label_set_label (GTK_LABEL (widget), profile_kind_text);
+ }
+
+ /* set colorspace */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_colorspace"));
+ profile_colorspace = gcm_profile_get_colorspace (profile);
+ if (profile_colorspace == GCM_COLORSPACE_UNKNOWN) {
+ gtk_widget_hide (widget);
+ } else {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_colorspace"));
+ profile_colorspace_text = gcm_viewer_profile_colorspace_to_string (profile_colorspace);
+ gtk_label_set_label (GTK_LABEL (widget), profile_colorspace_text);
+ }
+
+ /* set vcgt */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_vcgt"));
+ gtk_widget_set_visible (widget, (profile_kind == GCM_PROFILE_KIND_DISPLAY_DEVICE));
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_vcgt"));
+ has_vcgt = gcm_profile_get_has_vcgt (profile);
+ if (has_vcgt) {
+ /* TRANSLATORS: if the device has a VCGT profile */
+ gtk_label_set_label (GTK_LABEL (widget), _("Yes"));
+ } else {
+ /* TRANSLATORS: if the device has a VCGT profile */
+ gtk_label_set_label (GTK_LABEL (widget), _("No"));
+ }
+
+ /* set basename */
+ filename = gcm_profile_get_filename (profile);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_filename"));
+ basename = g_path_get_basename (filename);
+ temp = g_markup_escape_text (basename, -1);
+ gtk_label_set_label (GTK_LABEL (widget), temp);
+ g_free (temp);
+
+ /* set size */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_size"));
+ filesize = gcm_profile_get_size (profile);
+ if (filesize == 0) {
+ gtk_widget_hide (widget);
+ } else {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_size"));
+ size_text = g_format_size_for_display (filesize);
+ gtk_label_set_label (GTK_LABEL (widget), size_text);
+ }
+
+ /* set new copyright */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_copyright"));
+ profile_copyright = gcm_profile_get_copyright (profile);
+ if (profile_copyright == NULL) {
+ gtk_widget_hide (widget);
+ } else {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_copyright"));
+ temp = gcm_utils_linkify (profile_copyright);
+ gtk_label_set_label (GTK_LABEL (widget), temp);
+ g_free (temp);
+ }
+
+ /* set new manufacturer */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_profile_manufacturer"));
+ profile_manufacturer = gcm_profile_get_manufacturer (profile);
+ if (profile_manufacturer == NULL) {
+ gtk_widget_hide (widget);
+ } else {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_profile_manufacturer"));
+ temp = gcm_utils_linkify (profile_manufacturer);
+ gtk_label_set_label (GTK_LABEL (widget), temp);
+ g_free (temp);
+ }
+
+ /* set new model */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_profile_model"));
+ profile_model = gcm_profile_get_model (profile);
+ if (profile_model == NULL) {
+ gtk_widget_hide (widget);
+ } else {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_profile_model"));
+ gtk_label_set_label (GTK_LABEL(widget), profile_model);
+ }
+
+ /* set new datetime */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_datetime"));
+ profile_datetime = gcm_profile_get_datetime (profile);
+ if (profile_datetime == NULL) {
+ gtk_widget_hide (widget);
+ } else {
+ gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "label_datetime"));
+ gtk_label_set_label (GTK_LABEL(widget), profile_datetime);
+ }
+
+ /* set delete sensitivity */
+ ret = gcm_profile_get_can_delete (profile);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "button_profile_delete"));
+ gtk_widget_set_sensitive (widget, ret);
+ if (ret) {
+ /* TRANSLATORS: this is the tooltip when the profile can be deleted */
+ gtk_widget_set_tooltip_text (widget, _("Delete this profile"));
+ } else {
+ /* TRANSLATORS: this is the tooltip when the profile cannot be deleted */
+ gtk_widget_set_tooltip_text (widget, _("This profile cannot be deleted"));
+ }
+
+ /* should we show the pane at all */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_graph"));
+ gtk_widget_set_visible (widget, show_section);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_profile_info"));
+ gtk_widget_set_visible (widget, TRUE);
+
+ if (clut_trc != NULL)
+ g_object_unref (clut_trc);
+ if (clut_vcgt != NULL)
+ g_object_unref (clut_vcgt);
+ g_object_unref (white);
+ g_object_unref (red);
+ g_object_unref (green);
+ g_object_unref (blue);
+ g_free (size_text);
+ g_free (basename);
+}
+
+/**
+ * gcm_viewer_set_combo_simple_text:
+ **/
+static void
+gcm_viewer_set_combo_simple_text (GtkWidget *combo_box)
+{
+ GtkCellRenderer *renderer;
+ GtkListStore *store;
+
+ store = gtk_list_store_new (4, G_TYPE_STRING, GCM_TYPE_PROFILE, G_TYPE_UINT, G_TYPE_STRING);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), GCM_VIEWER_COMBO_COLUMN_SORTABLE, GTK_SORT_ASCENDING);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "wrap-mode", PANGO_WRAP_WORD_CHAR,
+ "width-chars", 60,
+ NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
+ "text", GCM_VIEWER_COMBO_COLUMN_TEXT,
+ NULL);
+}
+
+/**
+ * gcm_viewer_startup_phase1_idle_cb:
+ **/
+static gboolean
+gcm_viewer_startup_phase1_idle_cb (GcmViewerPrivate *viewer)
+{
+ GtkWidget *widget;
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+
+ /* search the disk for profiles */
+ gcm_profile_store_search_default (viewer->profile_store);
+ g_signal_connect (viewer->profile_store, "changed", G_CALLBACK(gcm_viewer_profile_store_changed_cb), viewer);
+
+ /* update list of profiles */
+ gcm_viewer_update_profile_list (viewer);
+
+ /* select a profile to display */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "treeview_profiles"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ path = gtk_tree_path_new_from_string ("0");
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+
+ return FALSE;
+}
+
+/**
+ * gcm_viewer_setup_drag_and_drop:
+ **/
+static void
+gcm_viewer_setup_drag_and_drop (GtkWidget *widget)
+{
+ GtkTargetEntry entry;
+
+ /* setup a dummy entry */
+ entry.target = g_strdup ("text/plain");
+ entry.flags = GTK_TARGET_OTHER_APP;
+ entry.info = 0;
+
+ gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, &entry, 1, GDK_ACTION_MOVE | GDK_ACTION_COPY);
+ g_free (entry.target);
+}
+
+/**
+ * gcm_viewer_profile_store_changed_cb:
+ **/
+static void
+gcm_viewer_profile_store_changed_cb (GcmProfileStore *profile_store, GcmViewerPrivate *viewer)
+{
+ /* clear and update the profile list */
+ gcm_viewer_update_profile_list (viewer);
+}
+
+/**
+ * gcm_viewer_graph_combo_changed_cb:
+ **/
+static void
+gcm_viewer_graph_combo_changed_cb (GtkWidget *widget, GcmViewerPrivate *viewer)
+{
+ gint active;
+
+ /* no selection */
+ active = gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+ if (active == -1)
+ return;
+
+ /* hide or show the correct graphs */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_graph_widgets"));
+ gtk_widget_set_visible (widget, active != 0);
+
+ /* hide or show the correct graphs */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_cie_axis"));
+ gtk_widget_set_visible (widget, active == 1);
+
+ /* hide or show the correct graphs */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_trc_axis"));
+ gtk_widget_set_visible (widget, active == 2);
+
+ /* hide or show the correct graphs */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_vcgt_axis"));
+ gtk_widget_set_visible (widget, active == 3);
+
+ /* hide or show the correct graphs */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_preview_input"));
+ gtk_widget_set_visible (widget, active == 4);
+
+ /* hide or show the correct graphs */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_preview_output"));
+ gtk_widget_set_visible (widget, active == 5);
+
+ /* save to GSettings */
+ g_settings_set_enum (viewer->settings, GCM_SETTINGS_PROFILE_GRAPH_TYPE, active);
+}
+
+/**
+ * gcm_viewer_setup_graph_combobox:
+ **/
+static void
+gcm_viewer_setup_graph_combobox (GcmViewerPrivate *viewer, GtkWidget *widget)
+{
+ gint active;
+
+ /* TRANSLATORS: combo-entry, no graph selected to be shown */
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), _("None"));
+
+ /* TRANSLATORS: combo-entry, this is a graph plot type (look it up on google...) */
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), _("CIE 1931 xy"));
+
+ /* TRANSLATORS: combo-entry, this is a graph plot type (what goes in, v.s. what goes out) */
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), _("Transfer response curve"));
+
+ /* TRANSLATORS: combo-entry, this is a graph plot type (what data we snd the graphics card) */
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), _("Video card gamma table"));
+
+ /* TRANSLATORS: combo-entry, this is a preview image of what the profile looks like */
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), _("Image preview (input)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX(widget), _("Image preview (output)"));
+
+ /* get from settings */
+ active = g_settings_get_enum (viewer->settings, GCM_SETTINGS_PROFILE_GRAPH_TYPE);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active);
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char **argv)
+{
+ guint retval = 0;
+ GOptionContext *context;
+ GtkWidget *main_window;
+ GtkWidget *widget;
+ guint xid = 0;
+ GError *error = NULL;
+ GtkTreeSelection *selection;
+ GdkScreen *screen;
+ GcmViewerPrivate *viewer;
+
+ const GOptionEntry options[] = {
+ { "parent-window", 'p', 0, G_OPTION_ARG_INT, &xid,
+ /* TRANSLATORS: we can make this modal (stay on top of) another window */
+ _("Set the parent window to make this modal"), NULL },
+ { NULL}
+ };
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init (&argc, &argv);
+
+ context = g_option_context_new ("gnome-color-manager prefs program");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_add_group (context, egg_debug_get_option_group ());
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ viewer = g_new0 (GcmViewerPrivate, 1);
+
+ /* ensure single instance */
+ viewer->application = gtk_application_new ("org.gnome.ColorManager.Profile", &argc, &argv);
+
+ /* setup defaults */
+ viewer->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
+
+ /* get UI */
+ viewer->builder = gtk_builder_new ();
+ retval = gtk_builder_add_from_file (viewer->builder, GCM_DATA "/gcm-viewer.ui", &error);
+ if (retval == 0) {
+ egg_warning ("failed to load ui: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* add application specific icons to search path */
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+ GCM_DATA G_DIR_SEPARATOR_S "icons");
+
+ /* maintain a list of profiles */
+ viewer->profile_store = gcm_profile_store_new ();
+
+ /* create list stores */
+ viewer->list_store_profiles = gtk_list_store_new (GCM_PROFILES_COLUMN_LAST, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING, GCM_TYPE_PROFILE);
+
+ /* create profile tree view */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "treeview_profiles"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+ GTK_TREE_MODEL (viewer->list_store_profiles));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (gcm_viewer_profiles_treeview_clicked_cb), viewer);
+
+ /* add columns to the tree view */
+ gcm_viewer_add_profiles_columns (viewer, GTK_TREE_VIEW (widget));
+ gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
+
+ main_window = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "dialog_viewer"));
+ gtk_application_add_window (viewer->application, GTK_WINDOW (main_window));
+
+ /* Hide window first so that the dialogue resizes itself without redrawing */
+ gtk_widget_hide (main_window);
+ gtk_window_set_icon_name (GTK_WINDOW (main_window), GCM_STOCK_ICON);
+ g_signal_connect (main_window, "delete_event",
+ G_CALLBACK (gcm_viewer_delete_event_cb), viewer);
+ g_signal_connect (main_window, "drag-data-received",
+ G_CALLBACK (gcm_viewer_drag_data_received_cb), viewer);
+ gcm_viewer_setup_drag_and_drop (GTK_WIDGET(main_window));
+
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "button_close"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_viewer_close_cb), viewer);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "button_preferences"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_viewer_preferences_cb), viewer);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "button_help"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_viewer_help_cb), viewer);
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "button_profile_delete"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_viewer_profile_delete_cb), viewer);
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "button_profile_import"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_viewer_profile_import_cb), viewer);
+
+ /* hidden until a profile is selected */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_graph"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_profile_info"));
+ gtk_widget_set_visible (widget, FALSE);
+
+ /* hide widgets by default */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "combobox_graph"));
+ gcm_viewer_set_combo_simple_text (widget);
+ gcm_viewer_setup_graph_combobox (viewer, widget);
+ g_signal_connect (widget, "changed",
+ G_CALLBACK (gcm_viewer_graph_combo_changed_cb), viewer);
+
+ /* use cie widget */
+ viewer->cie_widget = gcm_cie_widget_new ();
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_cie_widget"));
+ gtk_box_pack_start (GTK_BOX(widget), viewer->cie_widget, TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX(widget), viewer->cie_widget, 0);
+
+ /* use trc widget */
+ viewer->trc_widget = gcm_trc_widget_new ();
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_trc_widget"));
+ gtk_box_pack_start (GTK_BOX(widget), viewer->trc_widget, TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX(widget), viewer->trc_widget, 0);
+
+ /* use vcgt widget */
+ viewer->vcgt_widget = gcm_trc_widget_new ();
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_vcgt_widget"));
+ gtk_box_pack_start (GTK_BOX(widget), viewer->vcgt_widget, TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX(widget), viewer->vcgt_widget, 0);
+
+ /* use preview input */
+ viewer->preview_widget_input = GTK_WIDGET (gcm_image_new ());
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_preview_input"));
+ gtk_box_pack_end (GTK_BOX(widget), viewer->preview_widget_input, FALSE, FALSE, 0);
+ gtk_image_set_from_file (GTK_IMAGE (viewer->preview_widget_input), GCM_DATA "/figures/viewer-example.png");
+ gtk_widget_set_visible (viewer->preview_widget_input, TRUE);
+
+ /* use preview output */
+ viewer->preview_widget_output = GTK_WIDGET (gcm_image_new ());
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_preview_output"));
+ gtk_box_pack_end (GTK_BOX(widget), viewer->preview_widget_output, FALSE, FALSE, 0);
+ gtk_image_set_from_file (GTK_IMAGE (viewer->preview_widget_output), GCM_DATA "/figures/viewer-example.png");
+ gtk_widget_set_visible (viewer->preview_widget_output, TRUE);
+
+ /* do we set a default size to make the window larger? */
+ screen = gdk_screen_get_default ();
+ if (gdk_screen_get_width (screen) < 1024 ||
+ gdk_screen_get_height (screen) < 768) {
+ gtk_widget_set_size_request (viewer->cie_widget, 50, 50);
+ gtk_widget_set_size_request (viewer->trc_widget, 50, 50);
+ gtk_widget_set_size_request (viewer->vcgt_widget, 50, 50);
+ gtk_widget_set_size_request (viewer->preview_widget_input, 50, 50);
+ gtk_widget_set_size_request (viewer->preview_widget_output, 50, 50);
+ } else {
+ gtk_widget_set_size_request (viewer->cie_widget, 200, 200);
+ gtk_widget_set_size_request (viewer->trc_widget, 200, 200);
+ gtk_widget_set_size_request (viewer->vcgt_widget, 200, 200);
+ gtk_widget_set_size_request (viewer->preview_widget_input, 200, 200);
+ gtk_widget_set_size_request (viewer->preview_widget_output, 200, 200);
+ }
+
+ /* show main UI */
+ gtk_widget_show (main_window);
+
+ /* set the parent window if it is specified */
+ if (xid != 0) {
+ egg_debug ("Setting xid %i", xid);
+ gcm_window_set_parent_xid (GTK_WINDOW (main_window), xid);
+ }
+
+ /* refresh UI */
+ widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "combobox_graph"));
+ gcm_viewer_graph_combo_changed_cb (widget, viewer);
+
+ /* do all this after the window has been set up */
+ g_idle_add ((GSourceFunc) gcm_viewer_startup_phase1_idle_cb, viewer);
+
+ /* wait */
+ gtk_application_run (viewer->application);
+out:
+ g_object_unref (viewer->application);
+ if (viewer->settings != NULL)
+ g_object_unref (viewer->settings);
+ if (viewer->builder != NULL)
+ g_object_unref (viewer->builder);
+ if (viewer->profile_store != NULL)
+ g_object_unref (viewer->profile_store);
+ g_free (viewer);
+ return retval;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]